Dart Programming - Classes

Dart is an object-oriented programming language that also supports mixin-based inheritance mechanisms. Mixin related content will be explained below. Each object is an instance of a class, and all classes inherit from Object. Inheritance based on Mixin means that each class (except Object) has only one superclass, and the code of one class can be reused in the inheritance of multiple other classes

Declaring a Class

Use the new keyword and constructor to create new objects. The name of the constructor can be ClassName or ClassName.identifier.
In Dart 2.0, when creating new objects, the new keyword is optional. The latest version of Dart is currently 2.4.0, 2019-06-27 Dart development team released version 2.4.0 of Dart

1.1 Instance variables

class Point {
 
  num x;
  num y;
}

 

1.2 Constructor: The constructor defines a method with the same name as the class

Point(num x, num y) {
    this.x = x;
    this.y = y;
  }
  
  
  // Point(this.x, this.y);

 

1.3 Naming constructor

Point.fromJson(Map json) {
   x = json['x'];
    y = json['y'];
  }

  Point.namedConstructor(Map json){
    x = json['x'];
    y = json['y'];
  }

 

Use scenarios for named construction methods are: parse data scenarios in model classes.

To give a simple example: in the case of returning a list of data, the returned data may be an array containing multiple dictionaries, then when processing the corresponding data, the data needs to be parsed accordingly. The parsing process may use named construction methods. Take each dictionary as an example and extract it

[
    {
        "name":"Monday",
        "age":"1"
    },
    {
        "name":"Tuesday",
        "age":"1"
    },
    {
        "name":"Wednesday",
        "age":"1"
    },
    {
        "name":"Thursday",
        "age":"1"
    },
    {
        "name":"Friday",
        "age":"1"
    },
    {
        "name":"Saterday",
        "age":"1"
    },
    {
        "name":"Sunday",
        "age":"1"
    },
]

 

1.4 Example methods

num distanceTo(Point other) {
    var dx = x - other.x;
    var dy = y - other.y;
    return sqrt(dx*dx + dy*dy);
  }

1.5 Static methods

The methods modified with the static keyword are static methods, equivalent to class methods. It can be called directly using the class name


  static num distanceBetween(Point a, Point b) {
    var dx = a.x - b.x;
    var dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
  }
void classDemo() {

    var jsonData = jsonDecode('{"x":2, "y":2}');
    // Create a Point using Point().
    var p1 = new Point(1, 1);
    print('p1.x =?${p1.x}');
    print('p1.y =?${p1.y}');

    // Create a Point using Point.fromJson().
    var p2 = new Point.fromJson(jsonData);
    print('p2.x =?${p2.x}');
    print('p2.y =?${p2.y}');

    num distance = p2.distanceTo(p1);
    print('p1 p2 =: $distance');

    Map jsonData3 = {
      'x': 3,
      'y': 3,
    };

    Point p3 = Point.namedConstructor(jsonData3);
    print('p3.x?${p3.x}');
    print('p3.y?${p3.y}');
    
    num distance12 = Point.distanceBetween(p1, p2);
    print('p1 p2 $distance12');
    
    }

 

1.6 Static variables

Static variables are very useful for class-level state. I understand this sentence: static variables can be called directly by the class name

class Color {
  static const red =
      const Color('red'); // A constant static variable.
  final String name;      // An instance variable.
  const Color(this.name); // A constant constructor.
}

 

How to use

    String colorName = Color.red.name;
    print('colorName?$colorName');

 

1.7 set get method

The author below gives an example of the Set, Get methods of the left, top, width, and height of the Rectangle class

class Rectangle {
  num left;
  num top;
  num width;
  num height;

  Rectangle(this.left, this.top, this.width, this.height);

  // Define two calculated properties: right and bottom.
  num get right             => left + width;
      set right(num value)  => left = value - width;
  num get bottom            => top + height;
      set bottom(num value) => top = value - height;
}

 

2. extends, implements

extends

The keyword extends is used to inherit instance variables and methods of the parent class. Dart only supports single inheritance

implements

Every class implicitly defines an interface containing all the instance members of the class and of any interfaces it implements. If you want to create a class A that supports class B’s API without inheriting B’s implementation, class A should implement the B interface.

Each class implicitly declares an interface that contains all instance variables and the class has implemented.
If you want to create a class A without inheriting class B, but class A can access the API of class B, then class A should implement the interface of class B.
The above content, combined with the following example, the author's understanding is: Chicken implicitly declares the instance variables of Animal, and the methods that the Animal class has implemented. Chicken supports accessing the API of Class B without the inheritance of Animal.
A class can implement multiple APIs, so implements is a way to implement multiple inheritance

 

class Animal {
  String name;
  void ability() {
    print('Animal ???');
  }
}

class Bird extends Animal {
  void ability(){
    print('bird can fly');
  }
}

class Fish extends Animal {
  void ability(){
    print('fish can swim');
  }
}

class Dog extends Animal {
  void ability(){
    print('dog can bark');
  }
}

class Chicken implements Animal {
  String name;
  void ability() {
    print('chicken can lay eggs');
  }
}

 

3. mixin
Mixins are a way to reuse a class code in multi-class inheritance. I understand it, is the equivalent of a mixin class tool, using withkeyword used mixin class, you can use the code in the mixin.

Mixins are a way of reusing a class’s code in multiple class hierarchies.

To use a mixin, use the with keyword followed by one or more mixin names. The following example shows two classes that use mixins:

Mixin is a way to reuse certain code in multiple classes.
Mixin use, need to use withkeywords, with name behind with a mixin, with back with more mixin can name, and the code can be used multiple mixin simultaneously. The author below gives an example of a developer learning a basic language.

The author has defined a Developer mixin. If it is an iOS developer, you need to learn the basics of C language first. If you are an Android developer, you need to learn Java first. If you are a Flutter developer, you need to learn Dart language first

mixin Developer {
    bool isIOS = false;
    bool isAndroid = false;
    bool isFlutter = false;
    
   
    void needLearnBaseProgram () {
      if (isIOS) {
        print('Need Learn C Firstly');
      } else if (isAndroid) {
        print('Need Learn Java Firstly');
      } else if (isFlutter) {
        print('Need Learn Dart Firstly');
      } else {
        print('May be need Learn Other Language');
      }
    }
    
  }

class FlutterDeveloper with Developer {
    String name;
    FlutterDeveloper(String name) {
        isFlutter = true;
        this.name = name;
    }
}

 

4. abstract
Classes modified with abstract are referred to as abstract classes. Abstract classes are used to define interfaces and some implementations.

The author cites the following examples:

Created the People class and declared the abstract method of String skinColor (); and created and implemented the void ability () method

abstract class People {
  String skinColor();
  void ability() {
    print('All can Communicate');
  }

}

class YellowPeople extends People {
  @override
  String skinColor() {
    String color = 'Yellow';
    print(color);
    return color;
  }
}

class BlackPeople extends People {
  @override
    skinColor() {
      String color = 'black';
      print(color);
      return color;
    }
}

class WhitePeople extends People {
@override
  skinColor() {
    String color = 'White';
    print(color);
    return color;
  }
}

 

Usage

YellowPeople yellowPeople = YellowPeople();
yellowPeople.ability();
yellowPeople.skinColor();

WhitePeople whitePeople = WhitePeople();
whitePeople.ability();
whitePeople.skinColor();

BlackPeople blackPeople = BlackPeople();
blackPeople.ability();
blackPeople.skinColor();

 

Abstract classes cannot create instances.
An abstract method is a method without a method body. Abstract methods can only be written in abstract classes, not in other ordinary classes.
Example: If BlackPeople's skinColor has no method body and is not implemented, an error will be reported as follows: 'skinColor' must have a method body because 'BlackPeople' isn't abstract.
Try making 'BlackPeople' abstract, or adding a body to 'skinColor' .
Subclasses inheriting abstract classes must implement abstract methods
Taking WhitePeople as an example, if the skinColor method is not implemented, the following error will be reported:
Missing concrete implementation of People.skinColor.
Try implementing the missing method, or make the class abstract

 

5. override

5.1 override operator

Here I have added quotes to the override operator. As for the reason, after you have read the content below, you will understand the author's intention. Override and rewrite mentioned below mean the same thing.

First look at the sample code rewritten by the operator:

The Vector class rewrites the + operator and the subtraction operator to achieve the purpose that Vector can add and subtract directly. The author has also rewritten the toString method of the Vector class to facilitate viewing the x and y values ??of the Vector

class Vector {
  final int x;
  final int y;
  
  const Vector(this.x, this.y);

  Vector operator +(Vector v) {
    return Vector(x + v.x, y + v.y);
  }

  Vector operator -(Vector v) {
    return Vector(x - v.x, y - v.y);
  }
  
  @override
  String toString() {
    return 'runtimeType?' + this.runtimeType.toString() + '?x?' + x.toString() +'?y?' + y.toString();
  }
  
}

 

After using Vector's + and-operators and rewriting toString, the sample code and output result of using Vector are as follows

Vector v1 = Vector(1, 1);
    Vector v2 = Vector(2, 2);
    Vector v3 = v1 + v2;
    Vector v0 = v2 - v1;
    print(v0);
    print(v3);