Dart是面对象编程语言并且是基于mixin的继承方式。这意味着Dart不能继承多个类。

每个对象都是class类的实例,并且除了Null不是对象之外,其它对象都是Object派生对象。

基于Mixin的继承意味着每个类只有一个父类,一个类可以在多个类的主体中被重用,但Object对象除外。

Dart的扩展方法 Extension methods使你可以在不改变class类或者创建子类的情况下添加函数到类class。

在本教程中,我们将会说明如何在dart实例化类class,打印对象数据类型,初始化实例变量,访问实例变量。

Class类的成员

对象的成员由函数和数据,有时也成为方法与实例变量组成。当你调用一个方法时,是在一个对象上调用它。该方法可以访问对象的功能和数据。

你可以使用点符号.访问实例的变量和方法。当访问的属性可能为null空时,请使用?.代替.

var p = Point(2, 2);

// 访问p对象y实例变量.
assert(p.y == 2);

// 在对象p调用distanceTo()方法.
double distance = p.distanceTo(Point(4, 4));
// If p is non-null, set a variable equal to its y value.
var a = p?.y;

dart class实例化

你可以创建一个对象使用构造函数,构成函数的名称可以是类名ClassName或者ClassName.identifier

例如下面的代码创建Point 对象,使用Point()Point.fromJson() 构造函数。

你也可以使用可选的new调用构造函数创建对象,通常没有人会使用new关键词创建对象。

var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});

var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});

某些class类会提供一个常量构造函数,它可用于创建编译常量。要创建常量构造函数,请将const关键词放在构造函数名称的前面。

当创建两个同样的编译时常量,它们的实例是一样的。在常量的上下文,构造函数或者字面量可以省略const关键词。

您可以仅使用一次const关键词,在变量的前面添加const关键词创建常量的上下文。

var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);

assert(identical(a, b)); // 它们是同一个实例
// 这种方式使用非常多的常量关键词
const pointAndLine = const {
  'point': const [const ImmutablePoint(0, 0)],
  'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};

// 使用const关键词创建常量上下文
const pointAndLine = {
  'point': [ImmutablePoint(0, 0)],
  'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};

如果常量构造函数在常量的上下文外部并且在调用的时候没有使用const关键词,它会创建一个非常量的对象。

var a = const ImmutablePoint(1, 1); // 创建一个常量
var b = ImmutablePoint(1, 1); // 不会创建常量

assert(!identical(a, b)); // 两个不同实例

Dart 打印对象数据类型

要在运行时获得一个对象的类型,你可以访问ObjectruntimeType属性,它会返回对象的类型

要测试一个对象的类型请使用类型测试操作符,而不是ObjectruntimeType属性。

在产品环境,测试对象类型的语句是object is Typeobject is Type 会比object.runtimeType == Type更稳定。

print('The type of a is ${a.runtimeType}');

// is 
if(a is Stream){
  print
}

实例变量

class Point {
  double? x; // 声明instance x,初始值是空null
  double? y; // 声明instance y,初始值是空null
  double z = 0; // 声明instance z,初始值是空null
}

在Dart,所有未初始化的实例变量是的值是空null。所有实例变量都会有一个隐式getter方法

非最终Non-final实例变量和late final实例变量即使没有被初始化也会生成一个隐式的setter方法,更多详细的信息请参考Getters and setters

如果初始化一个非late实例变量,值会在创建实例的时候被创建。在late实例变量初始化之前构造函数和初始化列表会先被执行。

class Point {
  double? x; // 声明实例变量 x,初始值是空 null
  double? y; // 声明实例变量 y,初始值是空 null
}

void main() {
  var point = Point();
  point.x = 4; // 使用x的setter方法
  assert(point.x == 4); // 使用x的getter方法
  assert(point.y == null); // 值默认是null.
}

实例的变量可以是final,这种情况下final的实例变量必须初始化。要初始化final, 非late实例变量。

请使用构造函数的参数或者使用构造函数的初始化列表。如果你需要在构造函数的主体之后初始化一个final的实例变量。

你可以工厂构造函数或者使用late final。在使用late final的时候要小心,late final没有初始化器添加到API。

class ProfileMark {
  final String name;
  final DateTime start = DateTime.now();

  ProfileMark(this.name);
  ProfileMark.unnamed() : name = '';
}

结论

至此,你已经了解dart class的成员组成,dart class实例化,打印对象数据类型,初始化实例变量,访问实例变量。