• 基于 mixin 的继承
  • 根类是 Object

使用类成员

  • 数据
  • 函数
  1. var p = Point(2, 2);
  2. // Set the value of the instance variable y.
  3. p.y = 3;
  4. // Get the value of y.
  5. assert(p.y == 3);
  6. // Invoke distanceTo() on p.
  7. double distance = p.distanceTo(Point(4, 4));
  • ?. 避免对象为 null
  1. // If p is non-null, set its y value to 4.
  2. p?.y = 4;

使用构造函数

构造函数可以是:

  • ClassName
  • ClassName.identifier
  1. var p1 = Point(2, 2);
  2. var p2 = Point.fromJson({'x': 1, 'y': 2});
  • new 关键字是可选的
  1. var p1 = new Point(2, 2);
  2. var p2 = new Point.fromJson({'x': 1, 'y': 2});
  • 常量构造函数
  1. var p = const ImmutablePoint(2, 2);
  • 创建两次常量对象, 它们是相同的对象
  1. var a = const ImmutablePoint(1, 1);
  2. var b = const ImmutablePoint(1, 1);
  3. assert(identical(a, b)); // They are the same instance!
  • 不用写过多 const 关键字
  1. // 声明出所有 const
  2. // Lots of const keywords here.
  3. const pointAndLine = const {
  4. 'point': const [const ImmutablePoint(0, 0)],
  5. 'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
  6. };
  7. // Only one const, which establishes the constant context.
  8. const pointAndLine = {
  9. 'point': [ImmutablePoint(0, 0)],
  10. 'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
  11. };

获取对象类型

  • 返回类型对象
  • 运行时类型 runtimeType
  1. print('The type of a is ${a.runtimeType}');

实例变量

  • 每个实例变量隐含实现 getter 方法
  • 每个非 finall 实例变量隐含实现 setter 方法
  1. class Point {
  2. double x; // Declare instance variable x, initially null.
  3. double y; // Declare y, initially null.
  4. double z = 0; // Declare z, initially 0.
  5. }
  6. class Point {
  7. double x;
  8. double y;
  9. }
  10. void main() {
  11. var point = Point();
  12. point.x = 4; // Use the setter method for x.
  13. assert(point.x == 4); // Use the getter method for x.
  14. assert(point.y == null); // Values default to null.
  15. }

构造函数

  • 与类名相同
  • 命名构造函数
  • this
  1. class Point {
  2. double x, y;
  3. Point(double x, double y) {
  4. // There's a better way to do this, stay tuned.
  5. this.x = x;
  6. this.y = y;
  7. }
  8. }
  • 给实例变量赋值的语法糖
  1. class Point {
  2. double x, y;
  3. // Syntactic sugar for setting x and y
  4. // before the constructor body runs.
  5. Point(this.x, this.y);
  6. }

默认构造函数

如果没声明构造函数, dart 将会创建一个没有参数的构造函数, 并且调用父类的无参构造函数.

构造函数不会继承

没声明构造函数的子类只有默认的无参构造函数.

命名构造函数

  • 实现多个构造函数
  1. class Point {
  2. double x, y;
  3. Point(this.x, this.y);
  4. // Named constructor
  5. Point.origin() {
  6. x = 0;
  7. y = 0;
  8. }
  9. }

调用非默认超类构造函数

  • 默认情况下, 子类构造函数会调用父类非命名无参构造函数, 调用位置是子类构造函数体的开始.

各构造函数执行顺序:

  1. 初始化列表
  2. 父类无参构造函数
  3. 子类无参构造函数
  • 如果父类没有未命名的无参构造函数, 那么需要使用 : 符号来明确调用父类的一个构造函数
  • : 是初始化列表, 就是在子类没有创建之前, 使用初始化列表来初始化父类, 有了父类才能有子类
  1. class Person {
  2. String firstName;
  3. Person.fromJson(Map data) {
  4. print('in Person');
  5. }
  6. }
  7. class Employee extends Person {
  8. // Person does not have a default constructor;
  9. // you must call super.fromJson(data).
  10. Employee.fromJson(Map data) : super.fromJson(data) {
  11. print('in Employee');
  12. }
  13. }
  14. main() {
  15. var emp = new Employee.fromJson({});
  16. // Prints:
  17. // in Person
  18. // in Employee
  19. if (emp is Person) {
  20. // Type check
  21. emp.firstName = 'Bob';
  22. }
  23. (emp as Person).firstName = 'Bob';
  24. }

初始化列表

  • :
  • 使用 , 分隔
  • 不能使用 this
  1. // Initializer list sets instance variables before
  2. // the constructor body runs.
  3. Point.fromJson(Map<String, double> json)
  4. : x = json['x'],
  5. y = json['y'] {
  6. print('In Point.fromJson(): ($x, $y)');
  7. }
  • 在开发模型下, 用于验证参数
  1. Point.withAssert(this.x, this.y) : assert(x >= 0) {
  2. print('In Point.withAssert(): ($x, $y)');
  3. }
  • 初始化 final 字段
  1. import 'dart:math';
  2. class Point {
  3. final num x;
  4. final num y;
  5. final num distanceFromOrigin;
  6. Point(x, y)
  7. : x = x,
  8. y = y,
  9. distanceFromOrigin = sqrt(x * x + y * y);
  10. }
  11. main() {
  12. var p = new Point(2, 3);
  13. print(p.distanceFromOrigin);
  14. }

重定向构造函数

  1. class Point {
  2. double x, y;
  3. // The main constructor for this class.
  4. Point(this.x, this.y);
  5. // Delegates to the main constructor.
  6. Point.alongXAxis(double x) : this(x, 0);
  7. }

常量构造函数

  • 只要确保所有字段是 final 的
  1. class ImmutablePoint {
  2. static final ImmutablePoint origin =
  3. const ImmutablePoint(0, 0);
  4. final double x, y;
  5. const ImmutablePoint(this.x, this.y);
  6. }

工厂构造函数

  • factory 关键字
  • 可能不会创建新实例, 会从缓存中取出实例
  • factory 无法访问 this
  1. class Logger {
  2. final String name;
  3. bool mute = false;
  4. // _cache is library-private, thanks to
  5. // the _ in front of its name.
  6. static final Map<String, Logger> _cache =
  7. <String, Logger>{};
  8. factory Logger(String name) {
  9. return _cache.putIfAbsent(
  10. name, () => Logger._internal(name));
  11. }
  12. factory Logger.fromJson(Map<String, Object> json) {
  13. return Logger(json['name'].toString());
  14. }
  15. Logger._internal(this.name);
  16. void log(String msg) {
  17. if (!mute) print(msg);
  18. }
  19. }
  20. // 与普通构造函数使用方法相同
  21. var logger = Logger('UI');
  22. logger.log('Button clicked');
  23. var logMap = {'name': 'UI'};
  24. var loggerJson = Logger.fromJson(logMap);

方法

实例方法

  1. import 'dart:math';
  2. class Point {
  3. double x, y;
  4. Point(this.x, this.y);
  5. double distanceTo(Point other) {
  6. var dx = x - other.x;
  7. var dy = y - other.y;
  8. return sqrt(dx * dx + dy * dy);
  9. }
  10. }

Getters 和 Setters

  1. class Rectangle {
  2. double left, top, width, height;
  3. Rectangle(this.left, this.top, this.width, this.height);
  4. // Define two calculated properties: right and bottom.
  5. double get right => left + width;
  6. set right(double value) => left = value - width;
  7. double get bottom => top + height;
  8. set bottom(double value) => top = value - height;
  9. }
  10. void main() {
  11. var rect = Rectangle(3, 4, 20, 15);
  12. assert(rect.left == 3);
  13. rect.right = 12;
  14. assert(rect.left == -8);
  15. }

抽象方法

  • 抽象方法必须在抽象类中
  1. abstract class Doer {
  2. // Define instance variables and methods...
  3. void doSomething(); // Define an abstract method.
  4. }
  5. class EffectiveDoer extends Doer {
  6. void doSomething() {
  7. // Provide an implementation, so the method is not abstract here...
  8. }
  9. }

抽象类

  1. // This class is declared abstract and thus
  2. // can't be instantiated.
  3. abstract class AbstractContainer {
  4. // Define constructors, fields, methods...
  5. void updateChildren(); // Abstract method.
  6. }

隐式接口

  • 每个类隐式创建接口
  1. // A person. The implicit interface contains greet().
  2. class Person {
  3. // In the interface, but visible only in this library.
  4. final _name;
  5. // Not in the interface, since this is a constructor.
  6. Person(this._name);
  7. // In the interface.
  8. String greet(String who) => 'Hello, $who. I am $_name.';
  9. }
  10. // An implementation of the Person interface.
  11. class Impostor implements Person {
  12. get _name => '';
  13. String greet(String who) => 'Hi $who. Do you know who I am?';
  14. }
  15. String greetBob(Person person) => person.greet('Bob');
  16. void main() {
  17. print(greetBob(Person('Kathy')));
  18. print(greetBob(Impostor()));
  19. }
  • 实现多个接口
  1. class Point implements Comparable, Location {...}

扩展类

  • extends: 创建子类
  • super: 引用父类
  1. class Television {
  2. void turnOn() {
  3. _illuminateDisplay();
  4. _activateIrSensor();
  5. }
  6. // ···
  7. }
  8. class SmartTelevision extends Television {
  9. void turnOn() {
  10. super.turnOn();
  11. _bootNetworkInterface();
  12. _initializeMemory();
  13. _upgradeApps();
  14. }
  15. // ···
  16. }

重载成员

  • @override
  1. class SmartTelevision extends Television {
  2. @override
  3. void turnOn() {...}
  4. // ···
  5. }

可重载的操作符

image.png

  1. class Vector {
  2. final int x, y;
  3. Vector(this.x, this.y);
  4. Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  5. Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
  6. // Operator == and hashCode not shown. For details, see note below.
  7. // ···
  8. }
  9. void main() {
  10. final v = Vector(2, 3);
  11. final w = Vector(2, 2);
  12. assert(v + w == Vector(4, 5));
  13. assert(v - w == Vector(0, 1));
  14. }
  • 重写 == 时, 要求同时重写对象的 hashCode

noSuchMethod()

  • 在使用不存在的方法或实例变量时作出反应, 可以实现 noSuchMethod()
  1. class A {
  2. // Unless you override noSuchMethod, using a
  3. // non-existent member results in a NoSuchMethodError.
  4. @override
  5. void noSuchMethod(Invocation invocation) {
  6. print('You tried to use a non-existent member: ' +
  7. '${invocation.memberName}');
  8. }
  9. }

扩展方法

  1. import 'string_apis.dart';
  2. ...
  3. print('42'.padLeft(5)); // Use a String method.
  4. print('42'.parseInt()); // Use an extension method.

枚举类型

使用枚举

  • 声明
  1. enum Color { red, green, blue }
  • 每个枚举值有一个 index 属性
  1. assert(Color.red.index == 0);
  2. assert(Color.green.index == 1);
  3. assert(Color.blue.index == 2);
  • 获取枚举类型的所有值
  1. List<Color> colors = Color.values;
  2. assert(colors[2] == Color.blue);
  • 在 switch 中使用枚举
  1. var aColor = Color.blue;
  2. switch (aColor) {
  3. case Color.red:
  4. print('Red as roses!');
  5. break;
  6. case Color.green:
  7. print('Green as grass!');
  8. break;
  9. default: // Without this, you see a WARNING.
  10. print(aColor); // 'Color.blue'
  11. }

Mixins

多重继承.

  1. class Musician extends Performer with Musical {
  2. // ···
  3. }
  4. class Maestro extends Person
  5. with Musical, Aggressive, Demented {
  6. Maestro(String maestroName) {
  7. name = maestroName;
  8. canConduct = true;
  9. }
  10. }
  • mixins 类
  1. mixin Musical {
  2. bool canPlayPiano = false;
  3. bool canCompose = false;
  4. bool canConduct = false;
  5. void entertainMe() {
  6. if (canPlayPiano) {
  7. print('Playing piano');
  8. } else if (canConduct) {
  9. print('Waving hands');
  10. } else {
  11. print('Humming to self');
  12. }
  13. }
  14. }
  • 指定该 mixins 只能用在某类
  1. mixin MusicalPerformer on Musician {
  2. // ···
  3. }

类变量和类方法

  • static

静态变量

  1. class Queue {
  2. static const initialCapacity = 16;
  3. // ···
  4. }
  5. void main() {
  6. assert(Queue.initialCapacity == 16);
  7. }

静态方法

  1. import 'dart:math';
  2. class Point {
  3. double x, y;
  4. Point(this.x, this.y);
  5. static double distanceBetween(Point a, Point b) {
  6. var dx = a.x - b.x;
  7. var dy = a.y - b.y;
  8. return sqrt(dx * dx + dy * dy);
  9. }
  10. }
  11. void main() {
  12. var a = Point(2, 2);
  13. var b = Point(4, 4);
  14. var distance = Point.distanceBetween(a, b);
  15. assert(2.8 < distance && distance < 2.9);
  16. print(distance);
  17. }