flutter 中最详细的继承,多态,接口讲解
创始人
2024-04-10 20:02:10

flutter 中最详细的继承,多态,接口讲解

  • 前言
  • 一、继承(Extends)
  • 二、混合 mixins(with)
    • 2.1、最简单的mixin
    • 2.2、on 关键字,基于某个类型的mixin
    • 2.3、多个mixin
    • 2.4、mixin 怎么实现多继承
  • 三、接口的实现(implement)
  • 总结


前言

众所周知,dart 是一门单继承的语言,但是我们在日常开发中,会遇到各种各样的问题,比如,我们需要在dart 中实现多继承,那么改怎么办呢?本篇文章,我将和大家聊聊关于dart 中的继承,接口,混合的相关知识。

类型解决什么问题使用场景限制
extends子类继承子类继承父类只能继承一个父类,会继承父类的可见的属性和方法,不能继承构造函数。
Mixin(with)实现类似多继承不能通过多继承,获取一个类的实例不能有构造方法,可以有实例变量
Extension(on)使用 on 将mixin 限制为某个特定的类在无法修改被扩展类源码的情况下使用不能有构造方法和实例变量
Implement声明和实现的接口,实现解耦dart 不支持多继承,但是可以实现多接口

一、继承(Extends)

如何使用extends 关键字来继承父类

  • 子类会继承父类里面可见的属性和方法,但是不会继承构造函数
  • 子类能复写父类的getter 和 setter 方法
  • 子类重写超类的方法,要用@override
  • 子类调用超类的方法,要用super
  • 子类可以继承父类的非私有变量 (在dart 中,所有的变量和方法,默认都是公有的,我们可以使用 _ 来定义私有)

经过上面的解释,我们先来创建一个 person 的类,在类中定义人类的基本属性,私有的思想,基本的构造函数,和基本的运算

class Person {String? name;int? age;//  人类的思想是私有的,使用_thought 对子类不可见String? _thought;// 构造函数Person(this.name, this.age);// 计算这个人类是否成年bool get isAdult => (age ?? 0) >= 18;void run() {print("运行 person 类了");}
}

接下来我们再来定义一个学生 student 类,学生类会继承 person 类,并重写 和 调用 person 的方法

class Student extends Person {// 子类的构造函数,并使用super 调用了超类的方法, name 必传,age 可以为空, {int? age} 可选的意思Student(String name, {int? age}) : super(name, age);// 重写父类的方法@override// TODO: implement isAdultbool get isAdult => (age ?? 0) > 20;@overridevoid run() {// TODO: implement run// super.run(); 如果把这里注释掉,就无法调用到超类的run() 方法了。super.run();print("运行 student 类了");}//  子类自己的方法void studentRun() {print("运行 studentRun 类了");}
}

接下我们使用main 方法,来验证上面的写的内容

void main() {
//   调用学生自己的方法, 传入姓名 和 年龄Student student = Student("tiger");//访问父类属性,并赋值student.age = 18;//  父类中,我们大于等于18岁是成人,但是在student 中,我们重写了父类的Adult ,设置成了20, 因此下面输出为 falseprint(student.isAdult);// 调用父类的方法student.run();
}

运行上面的代码,我们可以得到下图中的输出内容:

image-20221117111853276

接下来我们改造一下main 中的代码,一起来学习一下,继承中是如何使用多态的

void main() {// 继承中多态的使用,这里 age: 18 传了可选参数agePerson person = Student("tiger", age: 18);// 调用超类的方法  需要注意的是,这里无法调用student 子类的方法,因为使用多态生成的对象是person, person 中没有student 的方法,如studentRun() 方法person.run();// 使用 is 的意思就是,将person 转化成 student 的对象,这样就可以访问子类的方法了。if (person is Student) {person.studentRun();}
}

代码运行结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yo1D43QX-1668667242626)(https://s2.loli.net/2022/11/17/EBmQMpI9v5dAS6u.png)]

到这里,dart 中的继承我们就讲完了,需要注意的点就是,在继承中多态的使用。

二、混合 mixins(with)

mixins 的意思就是混入的意思,就是在类中,混入其它的功能,说白了就是现有类的基础上,引入一些新的变量,下面我们一起来看一下它的特点。

  • 作为mixins 的类只能继承自object,不能继承其他的类。
  • 作为mixins 的类不能有构造函数。
  • 一个类可以mixins 多个mixin 类。
  • mixins 不是继承,也不是接口,而是一种全新的特性。

2.1、最简单的mixin

下面我们先来写一个最简单的mixin

// mixin 本身可以是抽象的,可以定义各种方法和属性,等待后续类去实现
mixin TextMixin {
//  定义属性var mixinValue = 2;//  抽象方法void mixinTest01();void mixinTest02() {print("mixinTest02 的输出");}
}class MixinModel with TextMixin{@overridevoid mixinTest01() {// 该函数mixin 定义未实现,混入对象,必须要实现print("mixinTest01 需要实现此方法: ${mixinValue}");}}void main(){MixinModel model = MixinModel();model.mixinTest01();model.mixinTest02();print("mixinValue 调用的输出: ${model.mixinValue}");
}

运行上面的代码:
在这里插入图片描述

从上面的代码及输出中,我们可以得出:mixin 本身可以是抽象的,可以定义各种的方法和属性,等待后续的类去实现

2.2、on 关键字,基于某个类型的mixin

当使用on 关键字(限定类型),则表示该mixin 只能在那个类的子类中使用,这就代表了mixin 中可以调用那个类的方法和属性,请看源码。

class BaseMixin {void method() {print("method 的输出");}
}mixin TextMixin1 on BaseMixin {void test1() {print("test1");}int testValue = 2;void test2() {method();}void test3();
}class Test extends BaseMixin with TextMixin1 {@overridevoid test3() {// TODO: implement test3print("需要实现的 test3");}}void main() {Test test = Test();test.test1();test.test2();test.test3();print(test.testValue);
}

运行上面代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YMGcIr29-1668667242628)(https://s2.loli.net/2022/11/17/nhpLPqBOKix7SHu.png)]

2.3、多个mixin

前面我们学习了简单的mixin,mixin 的限定on 关键字,现在我们来看一下,多个mixin 是怎么实现的。

mixin TextMixin1 {
//  定义属性var mixinValue = 1;//  抽象方法void mixinTest01();void mixinTest02() {print(" TextMixin1 中 mixinTest02  的输出");}
}mixin TextMixin2 {
//  定义属性var mixinValue = 2;void mixinTest03() {print("TextMixin2 中 mixinTest03 的输出");}
}class Test with TextMixin1, TextMixin2 {@overridevoid mixinTest01() {// TODO: implement mixinTest01print("TextMixin1 中的抽象方法 mixinTest01 的实现");}
}void main() {Test test = Test();test.mixinTest01();test.mixinTest02();test.mixinTest03();print(test.mixinValue);
}

运行上面的代码,输出结果如下图

在这里插入图片描述

从上面的代码及运行结果中,我们会发现,如果多个mixin 存在冲突性问题 (如:都有mixinValue 属性),后面的会覆盖前面的,没有冲突的,则都会保留,所以会存在后面的mixin 会修改掉前面的mixin 的一部分逻辑代码,不需要直接继承,就可以直接实现覆盖,避免了更复杂的多继承关系。

2.4、mixin 怎么实现多继承

dart 是单继承的语言,但是有些时候,我们也需要实现多继承的关系,既然mixin 是dart 语言中的一种新特性,那么我们该怎么使用mixin 来实现多继承的关系呢?这里将揭晓答案,请看代码

class BaseMixin {void init() {print("BaseMixin init");}BaseMixin() {init();}
}mixin TextMixin1 on BaseMixin {void init() {print("TextMixin1 init start");super.init();print("TextMixin1 init end");}
}mixin TextMixin2 on BaseMixin {void init() {print("TextMixin2 init start");super.init();print("TextMixin2 init end");}
}class Test extends BaseMixin with TextMixin1, TextMixin2 {@overridevoid init() {print("Test init start");super.init();print("Test init end");}
}void main() {Test();
}

代码运行,执行结果如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X7sVQYH5-1668667242629)(/Users/tiger/Library/Application Support/typora-user-images/image-20221117135958044.png)]

从上面执行结果输出的log 打印顺序,是不是发现,我们已经解决了dart 中没有多继承关系的问题呢?

三、接口的实现(implement)

接口的实现,说白了就是定义一个抽象类,抽象类中仅仅定义方法,没有具体的实现,子类通过implement 的方法,在子类中进行实现具体的方法。

下面先来看一段代码

abstract class Run {var runValue;void runing() {print("runing");}
}abstract class Eat {void eat();
}class Person implements Run, Eat {@overridevar runValue = 100;@overridevoid eat() {// TODO: implement eatprint("Person 吃了 ${runValue} 个萝卜");}@overridevoid runing() {// TODO: implement runingprint("Person 跑了 ${runValue} 公里");}
}class Tiger extends Run with Eat {// 抽象类中实现的方法// 继承抽象类可以不用实现(子类继承父类方法,可以选择是否重新)@overridevoid runing() {// 继承抽象类,可以调用supersuper.runing();print("Tiger runing");}// eat 抽象类中需要实现的方法@overridevoid eat() {// TODO: implement eatprint("Tiger eat");}
}void main() {Person person = Person();person.runing();person.eat();Tiger tiger = Tiger();tiger.runing();tiger.eat();
}

代码运行结果如下

在这里插入图片描述

从上面的代码和执行结果,我们可以看出,implement 与 extends 最大的不同就是运行后面接上多个普通或者抽象类,当我们使用 B implement A 修饰时,那么A 中的所有的属性和方法都要在B 中去实现,无论它原来是抽象方法还是普通方法。

总结

Mixin:定义了组块

Mixin on:限定了使用组块的宿主必须要继承与某个特定的类,在mixin 中可以访问到该特定类的成员和方法。

with负责组合组块,而with 后面跟的类并不一定都是mixin的,abstract class 和普通的类都可以。

extends with 修饰符会覆盖同名的方法,with 中 后一个覆盖前面的一个。

相关内容

热门资讯

歌游内蒙古·欢乐冰雪季 | 冰... 转自:草原云晶莹的冰面之上,选手身着防寒装备,手持钓竿凝神静候。在额尔古纳冰雪欢乐季第三届中俄界河冰...
看空情绪爆表:美元对冲成本升至... 随着美国政治环境的高度动荡引发市场涌向看空对冲,美元交易员正以创纪录的成本押注美元将出现更深度的下跌...
本轮巴以冲突已致加沙地带716... 当地时间1月27日,加沙地带卫生部门公布最新统计报告,称在过去48小时内,加沙地带各医院共接收2名死...
汽车维修工程教育专业学什么 汽...   汽车维修工程教育专业学什么?  太阳教育网,某名企人力资源总监曾先生表示,汽车维修工程教育专业毕...
最新或2023(历届)辽宁财贸... 最新或2023(历届)军训时间尚未公布,以下是该校军训注意事项:军训时最好随身携带的物品  1、女孩...