Dart 是一种面向对象的语言,具有基于类和 mixin 的 遗产。每个对象都是一个类的实例,所有类 除了 Object 的后裔。基于 Mixin 的继承意味着,虽然每个类 (顶级舱除外) 正好有一个超类,一个类体可以在 多个类层次结构。扩展方法是一种 向类添加功能,而无需更改类或创建子类。类修饰符允许您控制库如何对类进行子类型化。NullObject?
使用类成员
对象的成员由函数和数据(分别为方法和实例变量)组成。调用方法时,会在对象上调用它:该方法有权访问该对象的函数,并且 数据。
使用点 () 来引用实例变量或方法:.
var p = Point(2, 2);
// Get the value of y.
assert(p.y == 2);
// Invoke distanceTo() on p.
double distance = p.distanceTo(Point(4, 4));
使用 instead of 避免异常 当最左边的操作数为 null 时:?..
// If p is non-null, set a variable equal to its y value.
var a = p?.y;
使用构造函数
您可以使用构造函数创建对象。 构造函数名称可以是 或 。例如 以下代码使用 AND 构造函数创建对象:
ClassNameClassName.identifierPointPoint()Point.fromJson()
var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});
以下代码具有相同的效果,但 在构造函数名称之前使用 optional 关键字:new
var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});
某些类提供常量构造函数。 若要使用常量构造函数创建编译时常量, 将关键字放在构造函数名称之前:const
var p = const ImmutablePoint(2, 2);
构造两个相同的编译时常量会导致单个 规范实例:
var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);
assert(identical(a, b)); // They are the same instance!
在常量上下文中,可以省略 before 构造函数 或字面意思。例如,查看以下代码,它创建了一个 const 映射:const
// Lots of const keywords here.
const pointAndLine = const {
'point': const [const ImmutablePoint(0, 0)],
'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};
除了关键字的第一次使用之外,您可以省略所有关键字:const
// Only one const, which establishes the constant context.
const pointAndLine = {
'point': [ImmutablePoint(0, 0)],
'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};
如果常量构造函数位于常量上下文之外 并且调用时没有 , 它创建一个非常量对象:const
var a = const ImmutablePoint(1, 1); // Creates a constant
var b = ImmutablePoint(1, 1); // Does NOT create a constant
assert(!identical(a, b)); // NOT the same instance!
获取对象的类型
若要在运行时获取对象的类型, 您可以使用属性 , 它返回一个 Type 对象。ObjectruntimeType
print('The type of a is ${a.runtimeType}');
使用类型测试运算符,而不是测试对象的类型。 在生产环境中,测试更稳定 比测试.runtimeTypeobject is Typeobject.runtimeType == Type
到目前为止,您已经了解了如何使用类。 本节的其余部分演示如何实现类。
实例变量
以下是声明实例变量的方法:
class Point {
double? x; // Declare instance variable x, initially null.
double? y; // Declare y, initially null.
double z = 0; // Declare z, initially 0.
}
使用可为 null 类型声明的未初始化实例变量的值为 。 不可为 null 的实例变量必须在声明时初始化。null
所有实例变量都会生成一个隐式 getter 方法。 还会生成非最终实例变量和不带初始值设定项的实例变量 隐式 setter 方法。有关详细信息, 查看 Getter 和 setter。late final
class Point {
double? x; // Declare instance variable x, initially null.
double? y; // Declare y, initially null.
}
void main() {
var point = Point();
point.x = 4; // Use the setter method for x.
assert(point.x == 4); // Use the getter method for x.
assert(point.y == null); // Values default to null.
}
初始化声明非实例变量的位置 设置创建实例时的值, 在构造函数及其初始值设定项列表执行之前。 因此,初始化表达式(在 ) 的非实例变量无法访问 。late=latethis
double initialX = 1.5;
class Point {
// OK, can access declarations that do not depend on `this`:
double? x = initialX;
// ERROR, can't access `this` in non-`late` initializer:
double? y = this.x;
// OK, can access `this` in `late` initializer:
late double? z = this.x;
// OK, `this.fieldName` is a parameter declaration, not an expression:
Point(this.x, this.y);
}
实例变量可以是 , 在这种情况下,它们必须只设置一次。 初始化非实例变量 在声明时, 使用构造函数参数,或者 使用构造函数的初始值设定项列表:finalfinallate
class ProfileMark {
final String name;
final DateTime start = DateTime.now();
ProfileMark(this.name);
ProfileMark.unnamed() : name = '';
}
如果需要为实例变量赋值 构造函数主体启动后,可以使用下列方法之一:final
- 使用工厂构造函数。
- 使用 ,但要小心:没有初始值设定项的 a 会向 API 添加一个 setter。late finallate final
隐式接口
每个类都隐式定义一个包含所有实例的接口 类及其实现的任何接口的成员。如果你想 创建一个支持类 B 的 API 而不继承 B 的类 A 实现时,类 A 应实现 B 接口。
类通过在子句中声明一个或多个接口,然后提供 接口。例如:implements
// A person. The implicit interface contains greet().
class Person {
// In the interface, but visible only in this library.
final String _name;
// Not in the interface, since this is a constructor.
Person(this._name);
// In the interface.
String greet(String who) => 'Hello, $who. I am $_name.';
}
// An implementation of the Person interface.
class Impostor implements Person {
String get _name => '';
String greet(String who) => 'Hi $who. Do you know who I am?';
}
String greetBob(Person person) => person.greet('Bob');
void main() {
print(greetBob(Person('Kathy')));
print(greetBob(Impostor()));
}
下面是指定一个类实现多个 接口:
class Point implements Comparable, Location {...}
类变量和方法
使用关键字实现类范围的变量和方法。static
静态变量
静态变量(类变量)对于类范围的状态和 常数:
class Queue {
static const initialCapacity = 16;
// ···
}
void main() {
assert(Queue.initialCapacity == 16);
}
静态变量在使用之前不会初始化。
此页面遵循风格指南 建议优先使用常量名称。lowerCamelCase
静态方法
静态方法(类方法)不会在实例上运行,因此 无权访问 . 但是,他们确实可以访问静态变量。 如以下示例所示, 直接在类上调用静态方法:this
import 'dart:math';
class Point {
double x, y;
Point(this.x, this.y);
static double distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
}
void main() {
var a = Point(2, 2);
var b = Point(4, 4);
var distance = Point.distanceBetween(a, b);
assert(2.8 < distance && distance < 2.9);
print(distance);
}
请考虑使用顶级函数,而不是静态方法,用于 常见或广泛使用的实用程序和功能。
可以使用静态方法作为编译时常量。例如,您 可以将静态方法作为参数传递给常量构造函数。