Dart是一个物件导向语言,同时支持混入(mixin)的继承机制。每个物件都是一个类别的实体,所有的类别都继承于object。基于Mixin的继承意味着每个类别(Object除外)都只有一个父类别,一个类别可以在其他多个类别继承中重複使用。使用new关键字和建构式来建立新的物件。建构式的名字可以为ClassName或者ClassName.identifier。
宣告类别
宣告一个类别,使用关键字class开头,后跟类别名称; 接着使用一对大括号包围程式码。如下所示
语法
class class_name { <fields> <getters/setters> <constructors> <functions> }
类别可包括以下内容:
栏位(fields) - 栏位是类别中宣告的变数。
getters和setters - 允许程式初始化和检索类别栏位的值,预设的getter/setter与每个类别相关联。但是可以通过显式定义setter/getter来覆盖预设值。
建构式(constructors) - 为类别的物件分配记忆体。
函式(functions) - 函式表示物件可以採取的操作,也称为方法。
以上称为类别的资料成员。
做一个範例如下,宣告一个类别Car。该类别有一个brand的栏位;一个简单的方法 disp(),列印出厂牌这个栏位的值。
class Car { // field String brand = 'Tesla'; // function void disp() { print(brand); }}
建立类别的实体(Creating Instance of the class)
语法
目前建立类别的实体,不用加上new, 这样看起来更简洁。直接让变数等于建构式即可。
var object_name = class_name([ arguments ]);
把上面的Car类别,建立出实体
void main() { var car1 = Car(); //建立 Car 的实体 物件:car1 print(car1.brand); //Tesla}class Car { // field String brand = 'Tesla'; // function void disp() { print(brand); }}
建构式
建构式是类别的特殊函式,负责初始化类别。建构式是一个与类别名称相同的函式,它是一个函式,因此可以传入参数。但是与函式不同的地方,在于建构式不能具有返回型别。如果未宣告建构式,则会预设无参数的建构式。
语法
class_name(parameter_list) { //constructor body }
用上面的Car类别来修改,加上含有一个参数的建构式。这里有用到 this 关键字, 代表物件本身。
void main() { var car1 = Car('Benz'); var car2 = Car('BMW'); print(car1.brand); car2.disp();}class Car { // field String brand = 'Tesla'; //constructors Car(String b) { this.brand = b; } // function void disp() { print('The brand of the car is $brand'); }}
命名建构式
由于Dart不支援同一名称但是不同参数的多形建构式,以 Car 类别为例子,只能有一个名称叫做Car的建构式,
若是需要建立其他的建构式,需要命名为其他名称来建立,例如 Car.fromBC(brand, color)来建立。
void main() { var car1 = Car('Benz'); var car2 = Car.fromBC('BMW', 'black'); car1.color = 'red'; car1.disp(); car2.disp();}class Car { // field String brand; String color; //constructors Car(String brand) { this.brand = brand; } //这里採用命名建构式,并使用简写方式建立 Car.fromBC(this.brand, this.color); // function void disp() { print('The brand of the car is $brand and color is $color.'); }}
Getters和Setter
Getters(存取器)和Setter(更改器)允许程式分别初始化和检索类栏位的值。
Getters:使用get关键字定义。没有参数,会回传值。
Setter:使用set关键字定义。只有一个参数,且不回传值。
语法
//getterreturn_type get identifier { }//setterset identifier { }
void main() { var car1 = Car('Benz', 'red'); var car2 = Car('BMW', 'blue'); car1.disp(); car2.disp(); car1.setColor = 'black'; print('The Color of this car reset to ${car1.getColor}');}class Car { // field String brand; String color; //constructors Car(this.brand, this.color); //Setter set setColor(String c) { color = c; } set setBrand(String b) { brand = b; } //getter String get getColor => color; String get getBrand => brand; // function void disp() { print('The brand of the car is $brand and color is $color.'); }}
静态(static)用法
利用static 可以实现,在相同的类别之间的物件,可以共享栏位值与函式。要注意的是,若修改了类别上的static 的值,则所有该类别产生的物件都会受到影响,使用时需特别小心。
void main() { var person1 = Person('Dragon', 'Chen'); var person2 = Person('Jefferson', 'Lin'); print(person1.showFullName); print(person2.showFullName); Person.sayHi(person1); Person.sayHi(person2); Person.label = 'Your name is'; print(person1.showFullName); print(person2.showFullName); Person.sayHi(person1); Person.sayHi(person2);}class Person { // field String firstName; String lastName; static String label = "Person's name is "; //constructors Person(this.firstName, this.lastName); //Setter set fullName(String f) { var temp = f.split(' ') ; firstName = temp.first; lastName = temp.last; } set setFirstName(String f) { firstName = f; } set setLastName(String l){ lastName = l; } //getter String get getFirstName => firstName; String get getLastName => lastName; String get showFullName => '$label $firstName $lastName'; // static function static void sayHi(Person p) { print('Hi $label ${p.firstName} ${p.lastName}'); }}
继承
extends: 关键字来继承类别。要注意的是,除了建构式之外,全部的成员都会继承。不支援多重继承。
super: 可呼叫父层变数,属性或函式等等。。
@override: 重载(reload),也就是重新定义父层的函式,但是参数的数量和型别必须匹配。
语法
class child_class_name extends parent_class_name
void main() { var circle1 = Circle(); circle1.area(); circle1.color = 'red'; print('my color is ${circle1.showColor}'); } class Shape { String color; void area() { print("show area"); } String get showColor => color; } class Circle extends Shape {}
void main() { var person1 = Person('Dragon','Chen'); var person2 = Doctor('Jefferson','Lin','Badboy'); print(person1); print(person2);} class Person { String firstName; String lastName; String get fullName => '$firstName $lastName'; Person(this.firstName, this.lastName);} class Doctor extends Person{ String nickName; Doctor(String f, String l, this.nickName) :super(f,l); @override String toString() => 'Hi Doctor $fullName, also known as $nickName';}
抽象类别(Abstract class)
使用abstract关键字定义一个抽象类别,一个不能被实体化的类别,抽象类别通常用来定义介面(interface)。
void main() { var doctor1 = Doctor('Dragon', 'Chen', 'DC'); print(doctor1.fullName);}abstract class Person { String firstName; String lastName; String get fullName; Person(this.firstName, this.lastName);}class Doctor extends Person { String nickName; Doctor(String f, String l, this.nickName) : super(f, l); @override String get fullName => 'Hi Doctor $firstName $lastName, also known as $nickName';}
例子中可以看出,实体化Doctor类别,而不是实体化Person。而Person类别中的 fullName为抽象的getter且未实作,因此在子类别 Doctor中需实作 fullName。
介面(Interface)
Dart语言中,并未定义interface这个关键字,而是类别本身就是介面,也就是说类别除了可以被继承也可以被实作(implements)。
void main() { var doctor1 = Doctor('Dragon', 'Chen', 'DC'); print(doctor1.fullName);}abstract class Person { String firstName; String lastName; String get fullName; Person(this.firstName, this.lastName);}class Doctor implements Person { String nickName; @override String firstName; @override String lastName; Doctor(this.firstName, this.lastName, this.nickName); @override String get fullName => 'Hi Doctor $firstName $lastName, also known as $nickName';}
上面的例子显示,实作介面,就像是Person类别先设定好该有的成员,然后Doctor类别将内容实作出来。
实现多个介面
实现多个介面,介面名称之间用逗号分隔。语法如下:
class identifier implements interface-1,interface_2,interface_4…….
void main() { var c = Calculator(); print('The gross total : ${c.retTot()}'); print('Discount :${c.retDis()}'); } class CalculateTotal { // ignore: missing_return int retTot() {} } class CalculateDiscount { // ignore: missing_return int retDis() {} }class Calculator implements CalculateTotal,CalculateDiscount { @override int retTot() { return 1000; } @override int retDis() { return 50; } }
混入(Mixin)
因为只能单一继承,若是想要增加别的类别的函式功能,类似多重继承,就是使用混入(mixin)。
可以使用关键字mixin来取代class来宣告一个混入的类别,该类别就是一个让别的类别混入的类别。
混入类别无法被继承,且没有建构式。若要限制使用混入的类别,可用on关键字指定。
使用 with 来添加混入的类别。
mixin ProgrammerSkills on Developer{ void coding(){ print('writing code'); }}class Developer extends Person with ProgrammerSkills, ManagerSkills{ ...}```