Dart abstract class mixin 究竟哪里不一样呢?

2020-06-16 16:21:37 浏览数 (1)

编程那么多年,C,C ,OC,Swift,JS,Java都有用过。但是最新实验了下Dart的abstract class mixin几个关键字,把我弄得有点迷糊,似乎他们之间可以互相替代的,究竟他们之间有什么不同,什么情况使用什么呢。

1.定义


关键字

作用

abstract

抽象类,在Java,C 中都是接口抽象类,可以定义属性和虚函数,等着实现类去实现定义的方法。相当于Swift和OC的protocol,Swift里可以使用extension实现默认方法,但是在Dart里抽象类可以直接默认实现方法和属性,只是不能新建实例类。

class

类,可以新建实例,可以extends,implements,Mixin

mixin

通过创建一个继承自 Object 且没有构造函数的类,来 实现 一个 Mixin 。 如果 Mixin 不希望作为常规类被使用,使用关键字 mixin 替换 class 。

2.abstract class


在Dart中特点:

  • 不能实例化
  • 接口抽象
  • 可以默认实现方式
  • 可以被别的类实现和继承,抽象类可以直接继承

代码例子说明:

2.1、abstract class 默认实现方法

需要使用 实现类 extends 之后调用,使用implements需要实现默认方法。

代码语言:javascript复制
main(List<String> args) {
  final wp = Woman();
  final m = Man("小明");
  wp.run();
  m.run();
}

abstract class Person {
  run() {
    print("奔跑");
  }
}

class Man extends Person {

}

class Woman implements Person {
  @override
  run() {
    print("女神跑步");
  }
}

打印结果:

代码语言:javascript复制
女神跑步
奔跑
2.2、抽象类被抽象类继承
代码语言:javascript复制
abstract class Person {
  Person(this.name);
  final String name;

  talk();
  run() {
    print("奔跑");
  }
}

abstract class Student extends Person {
  Student(String name) : super(name);
  int age;
  study() {
    print("学习");
  }

  hasClass();
}

class Child implements Student {
  @override
  int age;

  @override
  hasClass() {
    // TODO: implement hasClass
    throw UnimplementedError();
  }

  @override
  // TODO: implement name
  String get name => throw UnimplementedError();

  @override
  run() {
    // TODO: implement run
    throw UnimplementedError();
  }

  @override
  study() {
    // TODO: implement study
    throw UnimplementedError();
  }

  @override
  talk() {
    // TODO: implement talk
    throw UnimplementedError();
  }
 
}

总结:abstract class被abstract class继承,继承需要实现父类构造函数。

2.3、abstract class 被Class extends和implements的区别
代码语言:javascript复制
abstract class Person {
  Person(this.name);
  final String name;

  talk();
  run() {
    print("奔跑");
  }
}

class Man extends Person {
  Man(String name) : super(name);

  @override
  talk() {
    print("man talk");
  }
}

class Woman implements Person {
  @override
  String get name => "女神";

  @override
  run() {
    print("女神跑步");
  }

  @override
  talk() {
    print("女神说话");
  }
}

上面例子,Man 类继承Person 抽象类,Woman 类实现Person抽象类,可以看出区别如下:

  1. extends 自动生成abstract 的构造方法,implements则不会
  2. extends 不需要实现属性可以直接利用父类, implements需要实现。
  3. extends 不需要实现默认方法可以直接利用,implements需要实现。(重要)
  4. 接口定义方法 extends和implements都需要实现。

3. class

Dart的Class特点: 可以当做抽象接口类被实现

代码例子:

代码语言:javascript复制
class Person {
  final String name;
  Person(this.name);

  talk() {
    print("person talk");
  }

  run() {
    print("person run");
  }
}

class Woman implements Person {
  @override
  // TODO: implement name
  String get name => throw UnimplementedError();

  @override
  run() {
    // TODO: implement run
    throw UnimplementedError();
  }

  @override
  talk() {
    // TODO: implement talk
    throw UnimplementedError();
  }
  
}

4. mixin

通过创建一个继承自 Object 且没有构造函数的类,来 实现 一个 Mixin 。 如果 Mixin 不希望作为常规类被使用,使用关键字 mixin 替换 class 。

  1. mixin 没有构造函数,不能被实例化
  2. 可以当做接口使用,class 混入之后需要实现
  3. 默认方法不需要实现(这个是和abstract 的区别)
  4. 如果一个类with,方法相同,先执行本体方法,然后按照混入顺序,执行最后mixin方法。
  5. 可以使用on 指定混入的类类型,如果不是报错。

代码演示:

代码语言:javascript复制
main(List<String> args) {  
  final man = Man("男神");
  man.classes();
  man.study();
}

class Person {
  final String name;
  Person(this.name);

  talk() {
    print("person talk");
  }

  run() {
    print("person run");
  }
}

class Man extends Person with Student {
  Man(String name) : super(name);

  @override
  study() {
    print("man study");
  }

  classes() {
    print("三年8班");
  }
}

mixin Student {
  int age;
  study();
  classes() {
    print("三年二班");
  }

  run() {
    print("student run");
  }
}

打印结果:

代码语言:javascript复制
三年8班
man study

5. 总结


根据以上特性总结下,在工作中什么情况,使用哪种关系结构。

主关系

方式

子关系

用途

class

extends

abstrct

当需要共通的构建方法和默认属性、方法的时候,同时需要重新实现接口方法。

abstrct

extends

abstrct

子抽象,类似class 继承关系。

class

implements

abstrct

每一个子关系都需要抽象定义所有的接口规范 ,规范类不需要实例

class

implements

class

每一个子关系都需要抽象定义所有的接口规范 ,规范类需要实例化

class

with

mixin

主关系混入子关系的内容,子关系不需要实例化

class

with

class

主关系混入子关系的内容,子关系需要实例化

class

with on

mixin

主关系混入子关系的内容,主关系必须是一个特点的类型,子关系不需要实例化

0 人点赞