类型 | 解决什么问题 | 使用场景 | 限制 |
---|---|---|---|
extends | 子类继承 | 子类继承父类 | 可以有构造方法和实例变量 |
Mixin(with) | 实现类似多继承,能力集 | 不通过继承,获取一个类的能力 | 不能有构造方法,可以有实例变量 |
Extension(on) | 给系统类【例如String类添加功能】 | 在无法修改被扩展类源码的情况下 | 不能有构造方法和实例变量 |
Implement | 声明和实现的解耦 | 模版方法的实现【设计模式的一种】 | 暂无 |
继承(extends)
使用extends关键词来继承父类
- 子类会继承父类里面可见的属性和方法 但是不会继承构造函数
- 子类能复写父类的方法 getter和setter
- 子类重写超类的方法,要用@override
- 子类调用超类的方法,要用super
- 子类可以继承父类的非私有变量 (类中私有变量和函数的定义:名称前面带_)
class Person {
String? name;
int? age;
/// 构造函数
Person(this.name);
/// 私有属性,对于子类不可见
String? _birthDay;
/// 计算属性
bool get isAdult => (age ?? 0) >= 18;
void run() {
print('Person runing');
}
}
class Student extends Person {
/// 子类构造函数
Student(String? name) : super(name);
/// 重写父类属性
@override
bool get isAdult => (age ?? 0) > 20;
@override
void run() {
// super.run();
print('Student runing');
}
/// 子类自有方法
void study() {
print("Student can studying");
}
}
void main() {
Student student = Student("li sha");
/// 调用自己方法
student.study(); // Student can studying
/// 访问父类属性
student.age = 18;
/// 调用父类方法
student.run(); // Person runing
print(student.isAdult); // false
/// 继承中 多态的使用
Person person = Student('jekson ');
person.run(); //Student runing
// Tips: Error 这里无法访问到子类方法,因为使用多态生成的对象是Person,Person中没有study方法
// person.study(); //Student runing
/// 使用is 意思是:将person 转化成 Student对像,就可以访问子类方法了
if (person is Student) {
person.study();
}
}
tips: 注意继承中 多态的使用
混合 mixins (with)
mixins的中文意思是混入(两个类混合在一起),就是在类中混入其他功能。简单的理解,就是在现有类的基础上,引入一些新的变量和方法。
- 作为mixins的类只能继承自Object,不能继承其他类
- 作为mixins的类不能有构造函数
- 一个类可以mixins多个mixins类
- mixins不是继承,也不是接口,而是一种全新的特性。
最简单的mixin
mixin本身可以是抽象的,可以定义各种方法属性,也可以是抽象的,等后续类去实现
void main(List<String> args) {
XuModel model = XuModel();
model.xuTest2();
model.xutest1();
print('xuValue: ${model.xuValue}');
}
/// mixin本身可以是抽象的,可以定义各种方法属性,也可以是抽象的,等后续类去实现
mixin TestXuMixin {
// 定义属性
var xuValue = 3;
// 抽象方法
void xutest1();
void xuTest2() {
print('xuTest2');
}
}
class XuModel with TestXuMixin {
@override
void xutest1() {
// 该函数mixin 定义未实现,混入对象,必须要实现
print("xutest1 - xuValue : $xuValue");
}
}
基于某个类型的mixin
当使用on关键字(限定类型),则表示该mixin只能在那个类的子类使用了,那么结果显然的,mixin中可以调用那个类定义的方法、属性
class BaseObject {
void method() {
print('call method');
}
}
mixin TestMixin on BaseObject {
void test() {
print('test');
}
int testInt = 1;
void test2() {
method();
}
void test3(); // 抽象方法
}
class Test extends BaseObject with TestMixin {
@override
void test3() {
// TODO: implement test3
}
}
void main() {
Test().test(); // test
print(Test().testInt); // 1
Test().test2(); // call method
}
多个mixin
如果mixin存在冲突的部分,后面会覆盖前面的,没有冲突的则会保留,所以可以存在后面的mixin修改了前面的mixin的一部分逻辑的情况,不需要直接继承即可实现覆盖,避免了更复杂的继承关系
mixin TestMixin {
void test() {
print('test');
}
int testInt = 1;
void test2();
}
mixin TestMixin2 {
int testInt = 2;
void test3() {
print('test3');
}
}
class Test with TestMixin, TestMixin2 {
@override
test2() {
print('test2');
}
}
void main() {
Test().test(); // test
print(Test().testInt); // 2 后面会覆盖前面的mixin
Test().test2(); // test2
Test().test3(); // test3
}
mixin实现多重继承
mixin TestMixin on BaseClass {
void init() {
print('TestMixin init start');
super.init();
print('TestMixin init end');
}
}
mixin TestMixin2 on BaseClass {
void init() {
print('TestMixin2 init start');
super.init();
print('TestMixin2 init end');
}
}
class BaseClass {
void init() {
print('Base init');
}
BaseClass() {
init();
}
}
class TestClass extends BaseClass with TestMixin, TestMixin2 {
@override
void init() {
print('TestClass init start');
super.init();
print('TestClass init end');
}
}
void main() {
TestClass();
/// TestClass init start
/// TestMixin2 init start
/// TestMixin init start
/// Base init
/// TestMixin init end
/// TestMixin2 init end
/// TestClass init end
}
接口实现(implements)
接口的实现,基于定义的一个抽象类,抽象类中仅定义方法,没有具体的实现,子类通过implements的方法,在子类中实现具体的方法。
- implements与extends最⼤的不同就是允许后⾯接上多个普通或者抽象类,当我们使⽤B implement A修饰时,那么A中的所有的属性和⽅法都要在B中实现,⽆论它原来是抽象⽅法还是普通⽅法。
abstract class Run {
var runValue;
void runing() {
print('runding');
}
}
abstract class Eat {
void eat();
}
class Person implements Run, Eat {
@override
void runing() {
print("Person runing");
}
@override
void eat() {
print("Person eating");
}
@override
var runValue = 100;
}
class Lion extends Run with Eat {
/// 抽象类中实现的方法
/// 继承抽象类可以不用实现(子类继承父类方法,可以选择是否重写)
@override
void runing() {
/// 继承抽象类可以调用super
super.runing();
print("Lion runing");
}
@override
void eat() {
print("Lion eating");
}
}
void main(List<String> args) {
Person().runing();
Person().eat();
Lion().eat();
Lion().runing();
}
tips:
mixin:定义了组块。
mixin on:限定了使⽤组块的宿主必须要继承于某个特定的类;在mixin中可以访问到该特定类的成员和⽅法。
with负责组合组块,而with后⾯跟的类并不⼀定需要是mixin的,abstract class 和普通类都可以。
extends with 修饰会覆盖同名方法,with中后一个覆盖前一个