参考:https://www.dartcn.com/guides/language/language-tour#%E7%B1%BB
Dart
是一种基于类和 mixin
继承机制的面向对象的语言。 每个对象都是一个类的实例,所有的类都继承于 Object
。
基于 Mixin 继承 意味着每个类(除 Object
外) 都只有一个超类, 一个类中的代码可以在其他多个继承类中重复使用。
对象的由函数和数据(即方法和实例变量)组成。 方法的调用要通过对象来完成: 调用的方法可以访问其对象的其他函数和数据。
使用 (.) 来引用实例对象的变量和方法:
var p = Point(2, 2);
// 为实例的变量 y 设置值。
p.y = 3;
使用 ?. 来代替 . , 可以避免因为左边对象可能为 null , 导致的异常:
var p = Point(2, 2);
// 如果 p 为 non-null,设置它变量 y 的值为 4。
p?.y = 4;
通过 构造函数 创建对象。 构造函数的名字可以是 ClassName
或者 ClassName.identifier
。例如, 以下代码使用 Point
和 Point.fromJson()
构造函数创建 Point
对象:
var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});
使用对象的runtimeType
属性, 可以在运行时获取对象的类型, runtimeType
属性回返回一个 Type
对象。
print('The type of a is ${a.runtimeType}');
通过创建一个与其类同名的函数来声明构造函数
class Point {
num x, y;
Point(num x, num y) {
this.x = x;
this.y = y;
}
}
通常模式下,会将构造函数传入的参数的值赋值给对应的实例变量, Dart
自身的语法糖精简了这些代码:
class Point {
num x, y;
// 在构造函数体执行前,
// 语法糖已经设置了变量 x 和 y。
Point(this.x, this.y);
}
在没有声明构造函数的情况下,
Dart
会提供一个默认的构造函数。 默认构造函数没有参数并会调用父类的无参构造函数。
子类不会继承父类的构造函数。 子类不声明构造函数,那么它就只有默认构造函数 (匿名,没有参数) 。
有时构造函数的唯一目的是重定向到同一个类中的另一个构造函数。 重定向构造函数的函数体为空, 构造函数的调用在冒号(:)
之后。(类似于Android
中自定义 View需要实现多个构造函数时调用最终的构造函数)
class Point {
num x, y;
// 类的主构造函数。
Point(this.x, this.y);
// 指向主构造函数
Point.alongXAxis(num x) : this(x, 0);
}
当执行构造函数并不总是创建这个类的一个新实例时,则使用 factory
关键字。 例如,一个工厂构造函数可能会返回一个 cache
中的实例, 或者可能返回一个子类的实例。
(类似于Android
中单例模式)
以下示例演示了从缓存中返回对象的工厂构造函数:
class Logger {
final String name;
bool mute = false;
// 从命名的 _ 可以知,
// _cache 是私有属性。
static final Map _cache =
{};
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
提示: 工厂构造函数无法访问 this。
工厂构造函的调用方式与其他构造函数一样:
var logger = Logger('UI');
logger.log('Button clicked');
方法是为对象提供行为的函数。
对象的实例方法可以访问 this 和实例变量。 以下示例中的 distanceTo() 方法就是实例方法:
import 'dart:math';
class Point {
num x, y;
Point(this.x, this.y);
num distanceTo(Point other) {
var dx = x - other.x;
var dy = y - other.y;
return sqrt(dx * dx + dy * dy);
}
}
只定义接口不进行实现,而是留给其他类去实现。 抽象方法只存在于 抽象类 中。
定义一个抽象函数,使用分号(;)
来代替函数体:
abstract class Doer {
// 定义实例变量和方法 ...
void doSomething(); // 定义一个抽象方法。
}
class EffectiveDoer extends Doer {
@override
void doSomething() {
print("123");
// 提供方法实现,所以这里的方法就不是抽象方法了...
}
}
void main() {
var eff = EffectiveDoer();
eff.doSomething();
}
输出:
123
枚举类型也称为enumerations 或 enums
, 是一种特殊的类,用于表示数量固定的常量值。
使用 enum
关键字定义一个枚举类型:
enum Color { red, green, blue }
枚举中的每个值都有一个index getter
方法, 该方法返回值所在枚举类型定义中的位置(从 0 开始)。
例如,第一个枚举值的索引是 0 , 第二个枚举值的索引是 1。
assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);
使用枚举的values
常量, 获取所有枚举值列表(list
)。
List colors = Color.values;
assert(colors[2] == Color.blue);
Mixin
是复用类代码的一种途径, 复用的类可以在不同层级,之间可以不存在继承关系。
通过创建一个继承自 Object
且没有构造函数的类,来 实现 一个Mixin
。 如果 Mixin
不希望作为常规类被使用,使用关键字 mixin
替换 class
。 例如:
mixin Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}
通过 with
后面跟一个或多个混入的名称,来 使用 Mixin
, 下面的示例演示了两个使用 Mixin
的类:
class Musician extends Performer with Musical {
// ···
}
class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
// Musical 类中的变量
canConduct = true;
}
}
指定只有某些类型可以使用的 Mixin -
比如, Mixin
可以调用 Mixin
自身没有定义的方法 - 使用 on
来指定可以使用Mixin
的父类类型:
mixin MusicalPerformer on Musician {
// ···
}
mixin
详解可查看 Dart之Mixin详解
使用 static 关键字实现类范围的变量和方法。
Dart
中静态变量只到它们被使用的时候才会初始化。
而Java
中静态变量是随着类的加载而加载的,所以当类加载进内存的时候,静态变量就已经伴随着类的加载而初始化进内存了,并且静态变量只在类加载时加载一次,存放在方法区中的静态区中。
class Queue {
static const initialCapacity = 16;
// ···
}
void main() {
assert(Queue.initialCapacity == 16);
}
静态方法(类方法)不能在实例上使用,因此它们不能访问 this 。 例如:
import 'dart:math';
class Point {
num x, y;
Point(this.x, this.y);
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 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);
}
输出:
2.8284271247461903