All posts by admin

Futures, then, catchError, whenComplete

A Future represents a value or an error that will be available in the future. This generic class should be used whenever you’re working with time-consuming functions returning a result after a notable amount of time.

Cascade Operator

Give a ClosedPath class like so:

In the main, we call its functions to draw a shape, you’ll do something like so:

However, using the cascade operator, we can simply it to this:

Notice there is no semi-colon in the end. Instead, we use .. operator to depict calling another function on the same instance.

Factory Constructor

We create an abstract Shape. We force class that conforms to this abstraction a getArea() and name.
In order to generate instances according to json data, we implement a factory constructor called fromJson.

It takes in a JSON object, and then returns a Square, or a Circle.

Factory constructors can return instances of the subclass.
But standard constructors can ONLY return instances of the current class.

Notice that in the abstract class Shape below, we actually can return subclass Square and Circle.

shape.dart

We conform to Shape by implementing name and getArea().
We then create a constructor with required param side.

Circle.dart

We conform to Shape by implementing name and getArea.
We then create a constructor by having required param side.

Square.dart

Finally, we use it like so:

Composition vs Inheritance

A Stack has-a List
A Square is-a Shape.

Due to us using a Widget as abstract, when we implement from it, we’re of type Widget.
So class Button needs a type Widget, and we can use any.

Abstract classes in Dart

ref –

  • https://medium.com/@manoelsrs/dart-extends-vs-implements-vs-with-b070f9637b36
  • https://en.wikipedia.org/wiki/Dependency_inversion_principle
  • https://stackoverflow.com/questions/3108182/using-parameter-that-implements-multiple-interfaces-pre-generics
  • https://flutterbyexample.com/lesson/abstract-classes-and-interfaces

Dart has no interface keyword. Instead, all classes implicitly define an interface. Therefore, you can implement any class.

You can create an abstract class to be extended by children abstract classes, (or implemented) by a concrete class. Abstract classes can contain abstract methods (with empty bodies).

Let’s first take a look at base classes and inheritance. We have a base class Vehicle with a constructor and some properties.

We then create a Car class and extends from this Vehicle.

Furthermore, we create a Hatch, and then extends from Car.

Finally, Hatch, being on the grand child inherits properties from both parent and grandparent.

Inheritance allows us to create new classes that reuse, extend and/or modify pre-existing classes behavior. The pre-existing class is called superclass and the new class we’re creating is called derived class.

In Dart, we can inherit only one superclass, but inheritance is transitive.

If the class Hatch is derived from the class Car and this class is derived from class Vehicle, then Hatch will be derived from Vehicle.

Use extends to create derived class, and super when you want to refer to the superclass. When class Car extends Vehicle, all properties, variables, functions implemented in class Vehicle will be available in class Car.

Suppose you want to create your own Car class, without inhering all the properties, variables and functions of the Vehicle class, but you want to inherit only the Vehicle type.

To do this, the Car class must implement the Vehicle interface by using abstract classes.

Abstract classes cannot be Instantiated!

Follows the concept of Dependency Inversion Principle

Given an abstract class Shape, we cannot instantiate it. We can only extend from it.

We create the shapes that must implement this abstraction:

Circle

Square

main.dart

We can implement abstract classes from more than one interface

…however, we can only extend from one parent class

Let’s take a look at the basics
We have abstract class A with a()

and abstract class B with b()

When we have a class AB that implements both A and B, it means we must implement both a() and b()

If we do not, it will complain. Because essentially we conform to the interfaces. It’s a pact with our abstraction that we will be implementing them.

Even if the abstract interface method is implemented, we must implement it.

Concrete classes can be instantiated. We extend from concrete classes.
Abstract classes CANNOT be instantiated. We implement abstract classes.

Passing instances that implements an abstract class

When we’re dealing with abstractions, we can specify that the object that is being passed in must implement a certain abstract class.

In our example, we have abstract class Person. In our parameter for function gate, we say that the parameter named person is an object that must implement Person.

So we create an instance of class Kid, which implements Person. We then pass kid into the parameter and it will be valid to be used. This encourages dependency inversion principle where modules are loosely coupled.

But what if we want it to conform to multiple interfaces?

ref – https://stackoverflow.com/questions/3108182/using-parameter-that-implements-multiple-interfaces-pre-generics

There are basically three ways to go about doing this:

1) Use function parameters to check against each abstraction, and pass in the same object.

So we have our interfaces

We have a Person class that implements both abstract classes

We have a function that takes in both interfaces. Just with different names. Each param checks on one abstraction, and since we want to check on two, then we just use two params for it.
It does this during compile time.

Then if both passes, then just use your object to access whatever abstract method you need.

In main, we just pass in the same object. The params of connectIt will check each abstraction for us.

2) Create another abstract class that implements both

3) Simply use type Person instead of an abstraction in connectIt’s parameter definition.

Intricacies

As an abstract child class, if we were to simply use the parent abstract class’s property, it will display the value there. So the parent abstract class will need to initialize it from property declaration, or constructor initialization.

As an abstract child class, if we over-ride property from parent, and try to use it, we’ll get an error. This is because when we use over-ride, we’re declaring the property on the child class, instead of using the parent class’s property.

As an abstract child class, if we did over-ride property from parent, we need to make sure we initialize it either from declaration:

or constructor:

method override in Dart

Named params and Positional params

ref – https://stackoverflow.com/questions/13264230/what-is-the-difference-between-named-and-positional-parameters-in-dart

Dart’s optional parameters are optional in that the caller isn’t required to specify a value for the parameter when calling the function.

Optional parameters can only be declared after any required parameters.

Optional parameters can have a default value, which is used when a caller does not specify a value.

In the above code, port is optional and has a default value of 80.

You can call getHttpUrl with or without the third parameter.

You can specify multiple positional parameters for a function:

But from a new reader perspective, it’s hard to tell what 8080 and 5 mean.

Thus, you can use named optional parameters to create more readable APIs.

Named optional parameters

A parameter wrapped by { } is a named optional parameter. Here is an example:

You can call getHttpUrl with or without the third parameter. But if you do, you MUST use the parameter name when calling the function.

You can specify multiple named parameters for a function:

Because named parameters are referenced by name, they can be used in an order different from their declaration.

Note: You may use positional optional parameters or named optional parameters, but not both in the same function or method. The following is not allowed.

super constructor in Dart

Dart DOES NOT support multiple parent class. It can only extend from ONE parent class

So we create base class Anima. It uses a named required parameter. The brackets mean it is named, so when
others put in params, they are forced to put in the name age first. The required means this function must take in this parameter.

Since Animal has named param age, we must specify age in super()
Let’s use named param to better describe what the other constructor params mean:

Now we see that the child class Dog can sleep, which is derived from its parent.
It can also bark, which is its own functionality.

So it tells us that it goes into the parent class first. Creates the instance, and then comes back down to the child to construct.

exposing library level private vars in Dart

// ref – https://stackoverflow.com/questions/17488611/how-to-create-private-variables-in-dart/17488825

There is no private, public, protected in Dart. However we use _ to hide data at the library level, and then use getter and setters to expose these data.

In our example, we declare _balance to be a library level private variable.
We expose this to the world through getter balance.

Dart functions as first objects and using Alias