简单易懂的Dart基础语法,继承。

1,396 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

定义一个子类

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

class LGPerson {
  String? name;
  int? age;
  int? _height;
  bool get isFree => _height! < 110;
  run() {
    print('Person run...');
  }
}

class Student extends LGPerson {
  study(){
    print('study...');
  }
}

void extendsDemo(){
  Student st = Student();
  st.age = 19;
  st.run();
  st.study();
}

image.png

重写父类的属性

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

class Student extends LGPerson {
  study(){
    print('study...');
  }
  @override
  // TODO: implement isFree
  bool get isFree => age! < 18;
}

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

void extendsDemo(){
  Student st = Student();
  if (st is Student) {
    st.age = 19;
    st.run();
    st.study();
    print(st.isFree);
    print(st.toString()); /// 类似于OC的description
  }
}

image.png

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

class LGPerson {
  String? name;
  int? age;
  int? _height;
  bool get isFree => _height! < 110;
  run() {
    print('Person run...');
  }
  /// 默认构造方法
  LGPerson(){
    print('person的构造方法..');
  }
}

void extendsDemo(){
  Student st = Student();/// 这里调起了父类LGPerson的默认的构造方法
}

image.png

子类的构造方法

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

class LGPerson {
  String? name;
  int? age;
  int? _height;
  bool get isFree => _height! < 110;
  run() {
    print('Person run...');
  }
  LGPerson.init();
  LGPerson(this.name);
  LGPerson.withName(this.name);
}

此时,在子类Student实例化处会报错

image.png

按住option + enter,需要实现这三个方法中的任意一个 image.png

当然,我们也可以不实现父类的,只不过在创建自己的构造方法的时候指向父类的即可。

class Student extends LGPerson {
  // Student.withName(String? name) : super.withName(name); 父类的构造方法
  // Student(String? name) : super(name);父类的构造方法
  // Student.init() : super.init();父类的构造方法
   Student(): super.init(); /// 自定义的构造方法 这个写法有点像初始化列表

  study(){
    print('study...');
  }
  @override
  // TODO: implement isFree
  bool get isFree => age! < 18;

  @override
  run() {
    // TODO: implement run
    print('student run...');
  }
}

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

class Student extends LGPerson {
  final String subName;
   Student.withName(String? name) : subName = name!, super.withName(name);
  // Student(String? name) : super(name);
  // Student.init() : super.init();
   Student(): subName = 'hello', super.init();
}

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