继承
- 使用关键字extends继承一个类
- 子类会继承父类可见的属性和方法,不会继承构造方法
- 子类能够复写父类的方法、getter和setter
- 单继承,多态性
父类:
class Person {
String name;
int age;
String _gender;
bool get isAdult => age > 18;
set aAge(int age) {
this.age = age;
}
void run() {
print('Person class run');
}
}
子类:
class Student extends Person {
///重写父类getter方法
@override
bool get isAdult {
return this.age > 10;
}
///重写父类setter方法
@override
set aAge(int age) {
this.age = age * 10;
}
///重写父类方法
@override
void run() {
print('Student run...');
}
void study() {
print('Student study...');
}
}
调用:
void test() {
var student = Student();
student.age = 11;
student.aAge = 10;
student.name = 'Robin';
print(student.age); // 100
print(student.isAdult); // true
print(student.name); // Robin
student.run(); // Student run...
Person person = Student(); // 多态
if (person is Student) {
person.study(); // Student study...
}
}
继承中的构造方法
-
子类的构造方法默认会调用父类的无名无参构造方法
class SupClass { SupClass() { print('SupClass'); } } class SubClass extends SupClass {} void test() => SubClass(); // 会打印 SupClass
如果父类没有无名无参的构造方法,则需要显示调用父类的构造方法
-
在构造方法参数后面使用冒号:显示调用父类构造方法
class SupClass { String name; SupClass(this.name); SupClass.withName(this.name); } class SubClass extends SupClass { SubClass(String name) : super(name); // SubClass(String name) : super.withName(name); // SubClass.withName(String name) : super(name); } void test() { var sub = SubClass('Robin'); print(sub.name); // Robin }
构造方法执行顺序
父类的构造方法在子类构造方法体开始执行的位置调用(初始化列表)
-
如果有初始化列表,初始化列表会在父类构造方法之前执行
class SupClass { String name; SupClass(this.name); } class SubClass extends SupClass { final String isa; /// 初始化列表必须写在父类构造方法之前 /// 初始化列表和父类构造方法之间用逗号分隔 SubClass(String name,String isaa) : isa = isaa, super(name); }
抽象类
抽象类使用 abstract 表示,不能直接被实例化
-
抽象方法不用 abstract 修饰,无实现
abstract class AbstractClass { void abs(); }
抽象类可以没有抽象方法
有抽象方法的类一定得声明为抽象类
-
通过继承来使用,抽象类更像是接口
class SubAbstractClass extends AbstractClass { @override void abs() { // print } }
接口
类和接口是统一的,类就是接口
每个类都隐式的定义了一个包含所有实例成员的接口
如果是复用已有的类的实现,使用继承(extends)
-
如果只是使用已有类的外在行为,使用接口(implements)
class Person { String name; int get age => 18; void run() { print('Person run...'); } } class Student implements Person { @override String name; @override // TODO: implement age int get age => null; @override void run() { // TODO: implement run } } /// 利用抽象类的方式更像一个接口的用法 abstract class SupPerson { void supRun(); } class Runner implements SupPerson { @override void supRun() { // TODO: implement supRun } }
Mixins
-
Mixins 类似于多继承,是在多类继承中重用一个类代码的方式
必须先有extends才可以用with Mixin
main(List<String> args) { var d = D(); d.isa = 'isa'; d.a(); // 打印结果C.a()... A、B、C中都有a()方法,最终打印的是C.a()这说明与Mixin的顺序有关,因C在B的后面 } class A { String isa; void a() { print('A.a()...'); } } class B { void a() { print('B.a()...'); } void b() { print('B.b()...'); } } class C { // C() {} void a() { print('C.a()...'); } void b() { print('C.b()...'); } void c() { print('C.c()...'); } } class D extends A with B, C { void d() { print('D.d()...'); } }
作为Mixin的类不能有显示声明构造方法(上面代码段中类C中的默认构造方法如果写出来的话,class D mixin就会显示有错误)
作为Mixin的类只能继承自Object 即不能有除了Object的其他继承(如果class C 继承在上面所说的Person class D也会报错)
使用关键字with连接一个或多个minxin
一个稍复杂的mixin例子:
abstract class Engine {
void work();
}
class OilEngine implements Engine {
@override
void work() {
print('Work with oil');
}
}
class ElectricEngine implements Engine {
@override
void work() {
print('Work with electric');
}
}
class Tyre {
String name;
void run(){}
}
// 简写方式 前提是class Car没有其他属性或方法
class Car = Tyre with ElectricEngine;
// 完整写法 可以添加属性或方法
class TCar extends Type with ElectricEngine {
String name;
}
class Bus = Tyre with OilEngine;
操作符覆写/重载
-
覆写操作符需要在类中定义
返回类型 operator 操作符(参数1,参数2,...){ 实现体... return 返回值 }
如果覆写 ==,还需要覆写对象的hashCode getter方法
可覆写的操作符:
< | + | | | [ ] |
> | / | ^ | [ ]= |
<= | ~/ | & | ~ |
>= | * | << | == |
- | % | >> |
main(List<String> args) {
var person1 = Person(18);
var person2 = Person(18);
// person1 > person2; // 未覆写:The operator '>' isn't defined for the class
bool result = person1 > person2;
print(result); // false
person1.age;
print(person1['age']); // 18
print(person1 == person2); // 未覆写返回 false 覆写后返回:true
}
class Person {
int age;
Person(this.age);
bool operator > (Person person) {
return this.age > person.age;
}
int operator [] (String key) {
if (key == 'age') {
return this.age;
} else {
return 0;
}
}
@override
bool operator == (Object other) =>
identical(this, other) ||
other is Person &&
runtimeType == other.runtimeType &&
age == other.age;
@override
int get hashCode => age.hashCode;
}