前端学习Dart|第七节

620 阅读8分钟

前言

这里是前端学习Dart第七节,本节知识点:的相关知识。

视频地址:待上传

前面我们已知Dart是一种面向对象的语言,类对于Dart来说非常重要。

看一下Dart中class声明语法:

image.png

类的名称需符合前面章节中提到过的标识符命名规则。

类的定义包含一下内容

  • <fields> 字段 - 字段是类中声明的任何变量。字段表示与对象有关的数据。
  • <getters/setters> get和set方法 - 允许程序初始化和检索类字段的值。默认的getter/setter与每个类相关联。但是,可以通过显式定义setter/getter来覆盖默认值。
  • <constructors> 构造函数 - 负责为类的对象分配内存。
  • <functions> 函数 - 函数表示对象可以采取的操作。它们有时也被称为方法。

创建类的实例

image.png

如上代码,声明了Car类,Car类中有成员变量model, 成员函数printModel。随后main函数中进行了Car类的实例化。

实例化一个类的话需要new关键字(Dart2.0版本之后可以舍弃new关键字)。类实例化语法如下:

image.png

可以通过对象访问类的属性和函数。使用.用于访问类的数据成员的点表示法(成为句点)。

image.png

类的成员变量

类中声明的变量即为类的成员变量。

image.png

类的实例可以访问类的成员变量。

image.png

所有实例变量都生成隐式 getter 方法。 非 final 的实例变量同样会生成隐式 setter 方法。

类的成员变量初始化赋值的过程在构造函数及其初始化列表之前。初始化列表即为下文中冒号操作符(:)

构造函数

构造函数是类中的特殊函数,负责初始化类的变量,构造函数是一个函数,因此可以参数化。但是构造函数不能具有返回值,如果一个类未声明构造函数,默认提供无参数的构造函数。

Dart类包含两种构造函数,同名构造函数、命名构造函数。

同名构造

同名构造函数是最常见的构造函数形式。

image.png

可以看到类中包含this关键字,这里关联一下上下文,前面章节中有提及一句Dart中没有this,然而类这里有出现了,这是为什么呢?

近当存在命名冲突时,使用 this 关键字。 否则,按照 Dart 风格应该省略 this 。

image.png

如果命名不冲突,如上声明也是可以的。

构造函数有一种语法糖,可以精简的进行变量赋值。

image.png

可以理解为同名赋值的简化形式,这种形式也支持占位命名参数(可以回顾一下函数章节,参数模块)

image.png

几点注意事项:

  • 在没有声明构造函数的情况下,Dart会提供一个默认的构造函数。默认构造函数没有参数并会调用父类的无参构造函数
  • 子类不会继承父类的构造函数。子类不声明构造函数,那么它就只有默认构造函数(匿名,没有参数)

命名构造函数

命名构造函数可以为一个类实现多个构造函数,可以使用命名构造函数来更清晰的表明函数意图:

image.png

那么问题来了,命名构造函数可不可以被继承呢?可以试一下

image.png

命名构造函数不会被子类继承。

换一个情形,如果类没有默认构造函数,但是有命名构造函数。那么实例化的时候必须使用一种命名构造进行实例化。

image.png

继承子类,如果想要调用父类的命名构造函数,可以使用冒号,位置在函数体之前。

image.png

上图中,super.origin() 命令执行在 ThreePoint()默认构造函数之前,super.origin即调用Point类中的origin命名构造函数。

冒号和命名构造函数体之间不仅可以调用super.xx函数,还可以直接初始化实例变量。

image.png

可以看到super.xx函数前面插入了z变量的初始化,多个变量初始化可以逗号分隔,super函数必须放在最后一位。

还可以插入断言。

image.png

常量构造函数

如果类生成的对象是固定不变的,那么就可以把这些对象定义为编译时常量。为此可以定义一个const构造函数,并且声明所有实例变量为final

image.png

如果你的类,创建的对象永远不会改变,你可以在编译期就创建这个常量实例,并且定义一个常量构造函数,并且确保所有的成员变量都是final的。

因为是const类型,常量构造函数创建的实例是同一个标准实例。

image.png

在常量上下文中,构造函数作者字面量前的const可以省略。

image.png

工厂构造函数

当执行构造函数并不总是创建这个类的一个新实例时,则使用factory关键字。概念可以理解为多态的单例

image.png

工厂构造函数无法访问this

类的成员函数

在类中声明的函数即类的成员函数

image.png

上图中origin即为Point类的成员函数。

类的实例可以访问类的成员函数

image.png

Getter 和 Setter

Getter和Setter用于对于对象属性读和写的特殊方法。

image.png

未声明Getter和Setter的成员变量都有一个隐式的Getter,通常情况下还会有Setter,非通常的情况为final类型。

类的static

static的作用也是声明类的成员变量或者成员函数,使多个相同类型的类对象,共享同一个成员变量的实例。

image.png

static修饰的成员变量成为静态变量,静态变量只有它们被用到的时候才会初始化。

image.png

相应的静态函数也可以如上声明,静态函数不能在实例中使用,因此它们不能访问this。

静态函数可以当做编译时常量使用。 例如,可以将静态方法作为参数传递给常量构造函数。

抽象类

抽象类通过abstract修饰符来装饰,抽象类不可实例化。抽象类通常定义接口或者部分实现。

抽象类中包含抽象方法, 抽象方法的定义为没有函数体的方法。

image.png

上面eat方法就是一个抽象方法,后面的函数体被省略掉,具体如何实现交给子类。

image.png

可以子类中实现了eat方法,猫继承(extends)自Animal抽象类。并且实现了抽象类的抽象方法。

接口

Dart中的接口也是通过abstrack关键字声明的,其他语言类似包含interface

image.png

还可以实现多接口

image.png

Extends & Implements

上述接口与抽象类的例子中分别使用类extendsimplements, 我们大体理解为两者都是“继承”的某种实现,那他们有什么区别呢?

Dart中只可以单继承,使用extends关键字。

extends继承的几个特点

  • 子类可以继承父类中可见的属性和方法
  • 子类可以通过super关键字调用父类的方法。
  • 子类不会继承父类的构造函数

如果 A extends B 的话,如果B是普通类,A中可以使用B中所有可见的函数和参数(不包含构造函数)。 如果B是抽象类,那么A中必须实现B中的抽象函数,因为B中的抽象函数没有函数体。

如果 A implements B ,无论B是普通类还是抽象类,A中必须实现B中的所有属性和方法,B中的函数体和属性值都不会被继承过来,AB当成了类的模板,只继承结构,不继承实现。所以这个概念叫做接口

implements另一个特点就是允许后面接上多个类。

Mixin

Mixin 是在多个类层次结构中重用类代码的一种方法,Mixin解决了“多继承”的问题。

上面是一个比较宏观的概念,下面我们白话一点讲。

mixin用于修饰类,和abstract类似。用于声明一个类模块。

image.png

如上声明了一个Brid mixin。其中包含action属性、fly成员函数。

声明角度来看,mixin类可以生命成员变量,成员函数,抽象方法。但是不可以进行实例化。

这时给别的类“安装”上这个mixin,使用with关键字。

image.png

可以看到输出为I can flyDog类使用了Brid mixin类模块中的成员函数。

类可以 with 多个 mixin,逗号分隔。

image.png

这样Dog又会飞又会跳了。

mixin可以限制使用范围,限定Brid mixin只能用在Animal类及其子类上,使用on关键字。

image.png

并且上述例子中,Brid mixin中可以使用 Animal 类中的成员。

类with的并不一定是mixin类,可以是普通类、抽象类。

image.png

用一个例子类体会一下mixin是如何解决“多继承”问题的。

image.png

END

在本章节中我们学习了知识点:类的基本概念,implements、extends、mixins等相关类的概念。