编程那么多年,C,C ,OC,Swift,JS,Java都有用过。但是最新实验了下Dart的abstract class mixin几个关键字,把我弄得有点迷糊,似乎他们之间可以互相替代的,究竟他们之间有什么不同,什么情况使用什么呢。
1.定义
关键字 | 作用 |
---|---|
abstract | 抽象类,在Java,C 中都是接口抽象类,可以定义属性和虚函数,等着实现类去实现定义的方法。相当于Swift和OC的protocol,Swift里可以使用extension实现默认方法,但是在Dart里抽象类可以直接默认实现方法和属性,只是不能新建实例类。 |
class | 类,可以新建实例,可以extends,implements,Mixin |
mixin | 通过创建一个继承自 Object 且没有构造函数的类,来 实现 一个 Mixin 。 如果 Mixin 不希望作为常规类被使用,使用关键字 mixin 替换 class 。 |
2.abstract class
在Dart中特点:
- 不能实例化
- 接口抽象
- 可以默认实现方式
- 可以被别的类实现和继承,抽象类可以直接继承
代码例子说明:
2.1、abstract class 默认实现方法
需要使用 实现类 extends 之后调用,使用implements需要实现默认方法。
代码语言:javascript复制main(List<String> args) {
final wp = Woman();
final m = Man("小明");
wp.run();
m.run();
}
abstract class Person {
run() {
print("奔跑");
}
}
class Man extends Person {
}
class Woman implements Person {
@override
run() {
print("女神跑步");
}
}
打印结果:
代码语言:javascript复制女神跑步
奔跑
2.2、抽象类被抽象类继承
代码语言:javascript复制abstract class Person {
Person(this.name);
final String name;
talk();
run() {
print("奔跑");
}
}
abstract class Student extends Person {
Student(String name) : super(name);
int age;
study() {
print("学习");
}
hasClass();
}
class Child implements Student {
@override
int age;
@override
hasClass() {
// TODO: implement hasClass
throw UnimplementedError();
}
@override
// TODO: implement name
String get name => throw UnimplementedError();
@override
run() {
// TODO: implement run
throw UnimplementedError();
}
@override
study() {
// TODO: implement study
throw UnimplementedError();
}
@override
talk() {
// TODO: implement talk
throw UnimplementedError();
}
}
总结:abstract class被abstract class继承,继承需要实现父类构造函数。
2.3、abstract class 被Class extends和implements的区别
代码语言:javascript复制abstract class Person {
Person(this.name);
final String name;
talk();
run() {
print("奔跑");
}
}
class Man extends Person {
Man(String name) : super(name);
@override
talk() {
print("man talk");
}
}
class Woman implements Person {
@override
String get name => "女神";
@override
run() {
print("女神跑步");
}
@override
talk() {
print("女神说话");
}
}
上面例子,Man 类继承Person 抽象类,Woman 类实现Person抽象类,可以看出区别如下:
- extends 自动生成abstract 的构造方法,implements则不会
- extends 不需要实现属性可以直接利用父类, implements需要实现。
- extends 不需要实现默认方法可以直接利用,implements需要实现。(重要)
- 接口定义方法 extends和implements都需要实现。
3. class
Dart的Class特点: 可以当做抽象接口类被实现
代码例子:
代码语言:javascript复制class Person {
final String name;
Person(this.name);
talk() {
print("person talk");
}
run() {
print("person run");
}
}
class Woman implements Person {
@override
// TODO: implement name
String get name => throw UnimplementedError();
@override
run() {
// TODO: implement run
throw UnimplementedError();
}
@override
talk() {
// TODO: implement talk
throw UnimplementedError();
}
}
4. mixin
通过创建一个继承自 Object 且没有构造函数的类,来 实现 一个 Mixin 。 如果 Mixin 不希望作为常规类被使用,使用关键字 mixin 替换 class 。
- mixin 没有构造函数,不能被实例化
- 可以当做接口使用,class 混入之后需要实现
- 默认方法不需要实现(这个是和abstract 的区别)
- 如果一个类with,方法相同,先执行本体方法,然后按照混入顺序,执行最后mixin方法。
- 可以使用on 指定混入的类类型,如果不是报错。
代码演示:
代码语言:javascript复制main(List<String> args) {
final man = Man("男神");
man.classes();
man.study();
}
class Person {
final String name;
Person(this.name);
talk() {
print("person talk");
}
run() {
print("person run");
}
}
class Man extends Person with Student {
Man(String name) : super(name);
@override
study() {
print("man study");
}
classes() {
print("三年8班");
}
}
mixin Student {
int age;
study();
classes() {
print("三年二班");
}
run() {
print("student run");
}
}
打印结果:
代码语言:javascript复制三年8班
man study
5. 总结
根据以上特性总结下,在工作中什么情况,使用哪种关系结构。
主关系 | 方式 | 子关系 | 用途 |
---|---|---|---|
class | extends | abstrct | 当需要共通的构建方法和默认属性、方法的时候,同时需要重新实现接口方法。 |
abstrct | extends | abstrct | 子抽象,类似class 继承关系。 |
class | implements | abstrct | 每一个子关系都需要抽象定义所有的接口规范 ,规范类不需要实例 |
class | implements | class | 每一个子关系都需要抽象定义所有的接口规范 ,规范类需要实例化 |
class | with | mixin | 主关系混入子关系的内容,子关系不需要实例化 |
class | with | class | 主关系混入子关系的内容,子关系需要实例化 |
class | with on | mixin | 主关系混入子关系的内容,主关系必须是一个特点的类型,子关系不需要实例化 |