定义一个子类

Dart中的继承使用extends来继承一个类,子类会继承除了构造方法以外的属性和方法,Dart是单继承的。

  1. class LGPerson {
  2. String? name;
  3. int? age;
  4. int? _height;
  5. bool get isFree => _height! < 110;
  6. run() {
  7. print('Person run...');
  8. }
  9. }
  10. class Student extends LGPerson {
  11. study(){
  12. print('study...');
  13. }
  14. }
  15. void extendsDemo(){
  16. Student st = Student();
  17. st.age = 19;
  18. st.run();
  19. st.study();
  20. }

image.png

重写父类的属性

这里去重写父类的isFree的时候,自动生成@override关键字。

  1. class Student extends LGPerson {
  2. study(){
  3. print('study...');
  4. }
  5. @override
  6. // TODO: implement isFree
  7. bool get isFree => age! < 18;
  8. }

这里多肽的使用if (st is Student),因为所有的类都集成于Object,所以这里的LGPerson 省略了extends Object,Object里面有一个方法external String toString();这个类似于OC的description,也可以重写这个方法,返回的就是自定义的类的描述。

  1. void extendsDemo(){
  2. Student st = Student();
  3. if (st is Student) {
  4. st.age = 19;
  5. st.run();
  6. st.study();
  7. print(st.isFree);
  8. print(st.toString()); /// 类似于OC的description
  9. }
  10. }

image.png
子类继承父类的时候,也会调起默认的父类的构造方法

  1. class LGPerson {
  2. String? name;
  3. int? age;
  4. int? _height;
  5. bool get isFree => _height! < 110;
  6. run() {
  7. print('Person run...');
  8. }
  9. /// 默认构造方法
  10. LGPerson(){
  11. print('person的构造方法..');
  12. }
  13. }
  14. void extendsDemo(){
  15. Student st = Student();/// 这里调起了父类LGPerson的默认的构造方法
  16. }

image.png

子类的构造方法

我们在父类里面新增自定义的构造方法

  1. class LGPerson {
  2. String? name;
  3. int? age;
  4. int? _height;
  5. bool get isFree => _height! < 110;
  6. run() {
  7. print('Person run...');
  8. }
  9. LGPerson.init();
  10. LGPerson(this.name);
  11. LGPerson.withName(this.name);
  12. }

此时,在子类Student实例化处会报错
image.png
按住option + enter,需要实现这三个方法中的任意一个
image.png
当然,我们也可以不实现父类的,只不过在创建自己的构造方法的时候指向父类的即可。

  1. class Student extends LGPerson {
  2. // Student.withName(String? name) : super.withName(name); 父类的构造方法
  3. // Student(String? name) : super(name);父类的构造方法
  4. // Student.init() : super.init();父类的构造方法
  5. Student(): super.init(); /// 自定义的构造方法 这个写法有点像初始化列表
  6. study(){
  7. print('study...');
  8. }
  9. @override
  10. // TODO: implement isFree
  11. bool get isFree => age! < 18;
  12. @override
  13. run() {
  14. // TODO: implement run
  15. print('student run...');
  16. }
  17. }

Student(): super.init();这个写法有点像前文介绍的初始化列表。那么这个语法可不可以和初始化列表共用呢?答案是可以的,初始化列表的作用是给final变量赋值和校验传递的参数。

  1. class Student extends LGPerson {
  2. final String subName;
  3. Student.withName(String? name) : subName = name!, super.withName(name);
  4. // Student(String? name) : super(name);
  5. // Student.init() : super.init();
  6. Student(): subName = 'hello', super.init();
  7. }

需要注意的是,这里的subName的赋值一定要写在构造函数的前面。