Dart语言学习笔记(二)类型系统

啰啰嗦嗦的前言

软件发展的历史印证了应用层开发必然是OOP(Object Oriented Programming)(面向对象编程语言)语言的天下,安卓应用开发之前一直是使用jvm系语言(最开始是java,后来又有kotlin),但是java由于需要兼顾全平台,很多地方并不是为移动端量身定做,这就导致了某些方面无法做到最优,再加上java易主后oracle跟谷歌在版权问题上的各种不愉快,可能就导致了谷歌想降低安卓平台对java的依赖,后来就有了flutter,flutter使用dart语言。
扯远了,关键字只有OOP,相比java,dart是更彻底的OOP,一切都是对象。那么就从类和对象学起。

类的定义

写法跟JVM系语言都差不多,随便写一个:

abstract class Animal{
  //普通构造器
  Animal(String name, int age):
      assert(name != null),
      assert(age > -1),
      this.name = name, this.age = age{
      print("Animal's constructor is invoked");
  }
  //命名构造器的转发写法,调用自己的其他构造器
  //注意一旦这么写了,后面就不能接函数体了
  Animal.fromMap(Map map):
        this(map["name"] ?? "unknownAnimal", map["age"] ?? 0);
  //命名构造器的非转发写法,可以接函数体
  Animal.fromDynamic(dynamic object){
    this.name = object.name;
    this.age = object.age;
  }
  String name;
  int age;
  //来个抽象方法,这里不写abstract,没有方法体的方法就是抽象方法。
  //动物当然得会动才行
  void move();
}

上面的普通构造器其实可以简化,变成这样:

  Animal(this.name, this.age):
      assert(name != null),
      assert(age > -1){
      print("Animal's constructor is invoked");
  }

这种写法的含义是,构造器接受两个跟自己的域成员类型一致的变量,分别赋值给它们,因为我们定义的name是String,age是int,所以这里就需要第一个参数是String而第二个参数是int,assert语句会在赋值之前被执行。
注意:普通构造器的名字跟类名相同,而且每个类只能有一个普通构造器
下面这种写法用来让所有对构造器的调用都产生相同的对象:

class Planet{
  static String description = "这是一个行星,一旦命名就不会改名";
  static int orbitInvokedCount;
  final String name;
  const Planet(this.name);
  void showOrbit(){
    print("本来应该让你看到我运行的轨道,但想想还是算了");
    print("算上你,一共${++orbitInvokedCount}个傻帽被我气的发飙");
  }
}

如果这么写,类里面所有非静态成员都必须是final。这种类也是可以被继承的。

继承(extends)

随便写个子类:

class Rabbit extends Animal{
  Rabbit(String name, int age) : super(name, age);
  @override
  void move() {
    print("兔子蹦蹦跳跳的往前走");
  }
}

一个类如果不显示指定构造器,那么它就有一个无参的普通构造器,如果指定了有参构造器,子类就必须在它和其他命名构造器里选择一个实现(如果有命名构造器),以上例子我选择了实现普通构造器,当然也可以实现命名构造器:

class Rabbit extends Animal{
  Rabbit.fromMapToo(Map map) : super.fromMap(map);
  @override
  void move() {
    print("兔子蹦蹦跳跳的往前走");
  }
}

可以看到,命名构造器不一定要跟父类同名,简单来说,有办法能把这个类实例化就行。不管是普通构造器还是什么途径都行。

实现(implements)

注意:在dart里,一个类在定义的时候就同时产生了两个东西,一个是你写的完整定义以及行为,另一个是由他们抽象出来的接口,也就是说,当我定义了兔子类的时候,这个东西就同时代表两个概念:兔子这个类和像兔子的这个接口,它们的名字都是Rabbit。跟java不同,这里类的属性也是接口的一部分,估计“得益于”getter、setter语法糖。。。(无奈脸)

class RabbitDoll implements Rabbit{
  @override
  int age = 0;

  @override
  String name = "兔子娃娃";
  //这个类的构造函数不受Rabbit的约束
  RabbitDoll(this.age, this.name);
  RabbitDoll.fromWhat();

  @override
  void move() {
    print("兔子布偶不会走");
  }
}

混合(mixin)

混合的概念是把类的方法放入另一个类,这在jvm语言上应该是以组合的形式实现的,dart具体实现方式不明,上代码说明:

class Flyable{
  String trait = "会飞";
  void move(){
    print("老子会飞");
  }
  void showTrait(){
    print("这个东西的特征是$trait");
  }
}
class Sparrow with Flyable implements Animal{
  @override
  int age;
  @override
  String name;
}
class Dove extends Animal with Flyable{
  Dove(String name, int age) : super(name, age);
}

之前定义的animal类有一个抽象方法move,这个方法已经被Flyable实现,下面的Sparrow和Dove类分别以implements和extends的方式获得Animal的接口特征,具体实现都委托给被混入的Flyable了。
Dart的类型系统里是单继承多实现多混合,凡是带“多”的都是逗号分隔,这就势必考虑到一个问题那就是冲突问题,implements里不存在具体实现所以没有冲突问题,而多mixin的情况由于mixin类都有具体实现,如果一个特征相同的方法在多个mixin里都有实现那会如何?实验证明,写在后面的mixin会覆盖前面的实现。你调用这个方法时以最后的mixin为准,当然,前提是你方法体里不再次覆盖这个方法。而mixin的优先级又是高于父类实现的。
一句话总结:方法的优先级:自己的 > mixin列表[n]的 > mixin列表[0]的 > 父类的。一旦冲突,优先级低的就被覆盖掉。
mixin其实还有一个写法,是用mixin关键字定义:

mixin AnimalLike implements Animal{
  
}

这种写法跟class的区别是:无法被实例化,不能extends其他类,只能implements接口,可以包含抽象成员。它可以使用on关键字限定只有特定类(及其子类)能混合它:

mixin AnimalLike on Dove implements Animal{
}

如果这么写了,只有Dove和Dove的子类可以with它,当然,on关键字后面是可以跟多个类的,用逗号分隔。
注意:这里说的是子类而不是接口,如果你用on限定了一个类,类X implements了它,那X是没法with这个mixin的。

一个类继承A混合了BCD,它的类型到底是什么?

这个问题其实没什么意义,之前说过,dart在声明一个类的时候就同时产生了同名的接口,而无论是is操作符(对应java的instanceof)还是泛型,里面写的其实都是上述的同名接口,我们在使用这些对象时关心的也只是它的方法特征(输入输出)而不是具体实现。
但如果硬要说的话,按java里那种父类的概念,子类的构造器要追随父类这倒是没错的。

  var sparrow = Sparrow();
  var dove = Dove("鸽子", 1);
  sparrow.move();
  sparrow.showTrait();
  var animals = List<Animal>();
  var flyables = List<Flyable>();
  animals.add(sparrow);
  flyables.add(sparrow);
  animals.add(dove);
  flyables.add(dove);

dove和sparrow既是Animal也是Flyable,不同的场景关注点不同,我们想联系一个朋友,那么微信和电话都能实现这个功能,这里我们就只关注通讯这个功能,至于微信还能做什么其他的,在这个应用场景就被忽略了。

访问限定修饰符

在dart里以_开头的是私有成员,跟es6一样,没什么好说的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容

  • Flutter日渐火爆,因此在进行Flutter学习前先学习一些其所使用的开发语言dart的基础,这篇文章主要学习...
    Samlss阅读 10,838评论 2 28
  • Dart 语言系列 Dart 语言入门 (一) Dart 语言入门 (二) Dart 语言入门 (三) Dart ...
    mark666阅读 1,681评论 2 8
  • Dart语言是使用flutter框架开发时候必备的语言,flutter是一个跨平台的框架,一套代码就可以完美实现安...
    砺剑锋成阅读 893评论 0 1
  • 此文章是v1.0+时编写,年代久远,小心有毒,谨慎食用!!! 一些重要概念 所有的东西都是对象,所有的对象都是类的...
    soojade阅读 10,040评论 2 27
  • 我要种一颗橄榄树 就在那条你每天必经的小路 守住了黄昏,守住了夜晚 直到它开花结果 直到你从它的身边路过 夏日的凉...
    洛風阅读 939评论 0 1