类
Dart语法样式: https://www.dartlang.org/guides/language/effective-dart/style
语法:https://www.dartlang.org/guides/language/language-tour
概览
- 重要概念
- 关键词
- 注释
- 变量
- 内置类型
- 函数
- 操作符
- 流程
- 异常
- 类
- 泛型
- 库
- 异步
- 发电机
- 可调用的类
- 分离
- 类型定义
- 元数据
Dart是一种具有类和基于mixin的继承的面向对象语言。每个对象
都是一个类的实例
,所有类都来自Object
。
基于Mixin的继承意味着虽然每个类(除了Object)只有一个超类,但是类体可以在多个类层次结构中重用。
特点:当最左边的操作数为null
时,使用?.
而不是.
避免异常:
构造函数
1 | class { |
默认构造函数
如果未声明构造函数,则会为您提供默认构造函数。默认构造函数没有参数,并在超类中调用无参数构造函数。
构造函数不是继承的
子类不从其超类继承构造函数。没有声明构造函数的子类只有默认(无参数,无名称)构造函数。
命名构造函数(多构造函数)
1 | // 命名构造函数:origin |
注意:构造函数不是继承的,这意味着超类的命名构造函数不会被子类继承。如果希望使用超类中定义的命名构造函数创建子类,则必须在子类中实现该构造函数。
一个完整的多构造函数写法:
1 | class { |
调用
1 | void classAboutMethod(){ |
结果为:
1 | 34 |
调用非默认的超类构造函数
执行顺序如下:
- 初始化列表
- 超类的无参数构造函数
- 主类的无参数构造函数
初始化列表
重定向构造函数
有时构造函数的唯一目的是重定向
到同一个类中的另一个构造函数
。重定向构造函数
的主体是空的
,构造函数调用出现在冒号(:)之后。
1 | class { |
调用:
1 | var pointAlongX = Point.alongX(11); |
结果为:
1 | 11 |
常量构造函数
如果你想使你的类生成永远不会更改的对象
,则可以使这些对象成为编译时常量
。为此,请 定义 const构造函数
并 确保 所有实例变量
都是final
。
1 | class ImmutablePoint { |
工厂建设者
在不需要总是创建新的实例的情况下可以使用 factory
关键字,例如下面这个例子表示:从缓存中返回对象的构造函数:
注意:工厂构造函数无权访问this。
1 | class { |
调用:
1 | var pointName = Point.name('Alice'); |
结果:
1 | 477440163 |
使用class成员
- 使用
.
来引用实例变量或方法
1 | var pointOrigin = Point(34,67); |
- 当
最左边
的操作数为null
时,使用?.
而不是.
避免异常:
1 | // 如果pointAbout不为空,那么设置x = 4; |
使用构造函数
一般情况
1 | var pointOrigin = Point(34,67); |
注意:在Dart2中,new
是可选关键字。
常量构造函数
有些类提供常量构造函数
。要使用常量构造函数创建编译时常量,请将const
关键字放在构造函数
名称之前
:
1 | var p = const ImmutablePoint(2, 2); |
如果构造2个相同
的编译时常量
,那么结果是:产生同一个
规范的实例:
1 | var a = const ImmutablePoint(1, 1); |
在常量上下文中,您可以省略
const构造函数或文字之前的内容。例如,查看此代码,该代码创建一个const映射:
1 | const pointAndLine = const { |
那么,除了第一次出现的const
外其他所有的const
关键字都可以省略。简写为:
1 | // Only one const, which establishes the constant context. |
如果常量构造函数在常量上下文之外
并且在没有const
的情况下调用,则会创建一个非
常量对象:
1 | var a = const ImmutablePoint(1, 1); // Creates a constant |
获取对象的类型
要在运行时获取对象的类型,可以使用Object
的runtimeType
属性,该属性返回
一个Type对象
。
1 | var pointAboutVal = Point.withVal(11, 21); |
结果为:
1 | the type of pointAboutVal is Point |
实例变量
以下是 声明 实例变量的方法:
1 | class { |
所有未初始化
的实例变量都具有该值null
。
所有实例变量都生成一个隐式getter方法
。非final实例变量也会生成隐式setter方法
。有关详细信息,请参阅Getters和setter。
1 | class Point { |
如果初始化声明它的实例变量(而不是构造函数或方法),则在创建实例时设置该值,该实例在构造函数及其初始化列表执行之前。
方法
方法是为对象提供行为的函数。
实例方法
对象的实例方法可以访问实例变量和this。
getters and setters
抽象方法
实例、getter和setter方法可以是抽象的,定义一个接口,但将其实现留给其他类。抽象方法只能存在于抽象类中。
1 | abstract class Doer { |
抽象类(abstract)
使用abstract
修饰符定义抽象类 - 无法实例化的类
。抽象类对于定义接口非常有用,通常还有一些实现。如果希望抽象类看起来是可实例化
的,请定义工厂构造函数
。
1 | abstract class Doer { |
Dart
与 Java
关于 抽象类
的区别:
Dart
:由abstract
关键字修饰的类就是抽象类,由关键字
决定。Java
:只要一个类中有未实现的方法,这个方法就是抽象类,由方法
决定。
隐式接口(interfaces)
每个类隐式的定义了一个接口,含有类的所有实例和它实现的所有接口。如果你想创建一个支持类 B 的 API 的类 A,但又不想继承类 B ,那么,类 A 应该实现类 B 的接口。
一个类实现一个或更多接口通过用 implements 子句声明,然后提供 API 接口要求。例如
1 | // A person. The implicit interface contains greet(). |
这里是具体说明一个类实现多个接口的例子:
1 | class Point implements Comparable, Location { |
特点:
这里的interface
接口和java不同
在于:不需要
定义interface
,任何class
都可以被implements
继承类(extends)
同Java
重写成员(@override)
同Java
注意:要在类型安全
的代码中缩小
方法参数 或 实例变量 的 类型
,可以使用covariant
关键字。
例子:
1 | class Animal { |
虽然此示例显示covariant
在子类型
中使用,但covariant
关键字可以放在超类
或子类方法
中。通常,超类方法
是放置它的最佳位置
。该covariant
关键字适用于单个参数
,并且在setter和字段上也受支持。
重写操作符
您可以覆盖下表中显示的运算符。
说明:表达e1 != e2
是!(e1 == e2)
的语法糖。
一个覆盖+
和-
运算符的类的示例:
1 | class Vector{ |
结果为:
1 | x is 2, y is 2 |
noSuchMethod()
可以通过重写noSuchMethod()可以发现或者对在代码中尝试使用不存在的方法
或者实例变量
作出反应。
1 | class A { |
你不能调用未实现的方法,除非以下一个是真实的:
接收器具有静态类型dynamic。
接收器有一个静态类型,它定义了未实现的方法(抽象是OK),接收器的动态类型的实现与类noSuchMethod() 中的实现不同Object。
枚举类型
枚举类型(通常称为枚举或枚举)是一种特殊类,用于表示固定数量
的常量值
。
使用enum
关键字声明枚举类型:
1 | enum Color { red, green, black } |
枚举中的每个值都有一个index
,从0
开始。如:
1 | assert(Color.black.index == 2); |
要获取枚举中所有值的列表
,请使用枚举values
常量。如:
1 | List<Color> colors = Color.values; |
结果为:
1 | 当前的索引为: 0 ,对应着的值为:Color.red |
switch
用法
1 | void doSwitch() { |
向类添加功能:mixin
mixins
是一种在多个类层次结构
中重用类代码
的方法。可以简单的理解为: mixin修饰的类
中定义了多个类
中公用
的变量
和方法
。
mix
是混合的意思
;in
是在……里面
。那么mixin
可以理解为:可以混合在指定类里面
的公用代码块
。用mixin
关键字代替class
关键字来实现一个可扩展的Object类
,且无需声明构造函数 :
mixin
本身可以
是抽象
的,可以定义各种方法属性,也可以是抽象的,等后续类去实现。
mixin使用
要使用 mixin
,请使用with
关键字后跟一个或多个
mixin关键字修饰的类。以下示例显示了使用有mixins
修饰的类:
1 | mixin TestMixin { |
注意:mixin
是 Dart 2.1
中引入的对关键字的支持。
mixin与on关键字:
要指定只有
某些类型可以使用mixin
——使用on
来指定所需的超类
,这样你的mixin
可以调用一个它自身没有定义
的方法:
1 | class BaseObject { |
当使用on
关键字后,则表示该mixin修饰的类
只能在那个类的子类
使用了。
多个mixin
1 | mixin TestMixin1 on BaseContext{ |
在TestMixin1
与TestMixin2
中都声明了一个intValue
变量,但是值不同。在class TestClass extends BaseContext with TestMixin1,TestMixin2
的顺序中,得到的结果是:
1 | 2 |
即:TestMixin2
中初始化的值。
那么改变一下with
的顺序呢?class TestClass extends BaseContext with TestMixin2,TestMixin1
,结果是:
1 | 1 |
由此可见:取值的是最后一个with
的类中的值。
类变量和方法
使用static
关键字实现类范围
的变量和方法。
静态变量
静态变量(类变量)
对于类范围
的状态
和常量
很有用:
1 | class Queue { |
注意:
- 静态变量在
使用之前
不会初始化。 - 遵循
样式指南
建议,优先使用lowerCamelCase
作为常量名称
。
静态方法
1 | class Point { |
注意:
- 对于常用或广泛使用的实用程序和功能,请考虑使用
顶级函数
而不是静态方法。
您可以使用静态方法作为编译时常量。例如,您可以将静态方法作为参数传递给常量构造函数。