重点:
- implements必须实现接口类中的所有属性和方法(普通方法和抽象方法)。
这篇博客写的很好:
www.jianshu.com/p/18e8d285c…
- Java和Dart的对比:
在使用Java语言设计类之间关系的时候,我们会接触到 组成单元 和 关系连接 这两类概念:
组成单元:普通类、abstract抽象类,interface接口。
关系连接:implements实现,extends继承。
而在Dart当中,对于这两类概念进行了增减:
组成单元:普通类,abstract抽象类、mixin。
关系连接:implements实现、extends继承、with混入。
最大的不同有两点:
去掉了interface。 增加了混入的概念。
一、组成单元
-
普通类
Java和Dart没有区别 -
抽象类
Java和Dart的抽象类定义时大体是一样的,我们可以在其中定义变量、普通方法、抽象方法,它和普通类最大的区别就是 抽象类不能实例化。
Java和Dart在使用抽象类时有一点不同:Dart在定义抽象方法时,不需要用abstract修饰。
abstract class DartAbs {
void absMethod(); //没有实现体的方法-抽象方法,Dart中不需要abstract修饰
}
- interface接口
Dart中没有interface关键字定义接口类,普通类和抽象类都可以作为接口类。
顺带我们复习一下Java中abstract和interface的一些要点:
- 抽象类和接口都不能被实例化。
- 抽象类要被子类继承,接口要被类实现。
- 接口只能做方法的声明,抽象类可以做方法的声明,也可以做方法的实现。
- 接口里定义的变量只能是公共的静态常量,抽象类中的变量可以是普通变量。
- 抽象类里的抽象方法必须全部被子类实现;接口的接口方法必须全部被子类实现,否则只能为抽象类。
- 抽象类里可以没有抽象方法。
- 如果一个类里有抽象方法,那么这个类只能是抽象类。
- 抽象方法要被实现,所以不能是静态的,也不能是私有的。
- 接口可继承接口,并可多继承接口,但类只能单继承。
二、连接关系
- extends继承
Dart和Java一样,都是单继承。
子类可以继承父类里面 可见的属性和方法。
对于Java来说,可见指的是非private修饰,
对Dart来说,指的是非下划线_开头。
子类调用父类的方法,使用super关键字。
子类不会 继承 父类的构造函数。
继承父类的方法,不一定需要重写
- implements实现
implements实现多个类或抽象类,实现了“多继承”
A implements B,A中都需要实现B中所有的属性和方法(不管是普通方法还是抽象方法),继承不一定需要重写!如果要创建一个 A 类,A 要支持 B 类的 API ,但是不需要继承 B 的实现, 那么可以通过 A 实现implements B 的接口。
class Implements {
String a;
void base() {
print('base');
}
void log() {
print('extends');
}
}
class Log implements Implements {
String a = "hello"; //没有这句,则会报错,因为必须实现接口类中所有的属性和方法
base() {
print('log#base');
}
log() {
print('log' + a);
}
}
void main() {
Log().log();
}
三、mixin,with混入
通过创建一个继承自 Object 且没有构造函数的类,来 实现 一个 Mixin 。 如果 Mixin 不希望作为常规类被使用,使用关键字 mixin 替换 class。
也就是说,with混入的类必须没有构造函数,可以是class定义的类,但是最好用mixin关键字来定义这样的类。
mixin MusicalPerformer on Musician {
// ···
}
mixin on
混入MusicalPerformer的类必须继承Musician
下面有个例子:
abstract class Super {
void method() {
print("Super");
}
}
class MySuper implements Super {
void method() {
print("MySuper");
}
}
mixin Mixin on Super {
void method() {
super.method();//15行
print("Sub");
}
}
class Client extends MySuper with Mixin {
}
输出
MySuper
Sub
第15行调用super.method()会先查找MyMixin中有没有对应的方法,发现有该方法,然后因为MyMixin限定子类必须继承或实现Super,所以第15行方法中的super.method()会调用MyMixin的子类所extend的父类的method方法,在这里就是MySuper的method()方法,所以输出MySuper,然后输出Sub。
四、冲突
如果同时存在extends, with,并且它们都定义了相同的方法名.
with修饰的会覆盖extends中修饰的同名方法。
with列表中后一个的会覆盖之前的。
再加上implements
class Extends {
void log() {
print('extends');
}
}
mixin Mixins {
void log() {
print('mixin');
}
}
mixin Mixins2 {
void log() {
print('mixin2');
}
}
class Implements {
void log() {
print('implements');
}
}
class Log extends Extends with Mixins, Mixins2 implements Implements {}
void main() {
Log().log();
}
输出结果为:mixin2
这里我们发现了一个奇怪的现象:虽然我们加上了implements,但是Dart居然没让我们实现Implements.log()方法!
这是因为在这种情况下,它识别到我们从with和extends中获得了log()方法的能力,因此调用的是Mixins2.log()。
假如我们对Implements#log方法进行实现:
class Log extends Extends with Mixins, Mixins2 implements Implements {
void log() {
print("implements log");
}
}
输出的结果为:implements log