類概述
- 普通類
- 變量
- 實(shí)例變量(創(chuàng)建對(duì)象后燎含,使用 對(duì)象.變量名 調(diào)用)
- 靜態(tài)變量(用static修飾贸弥,使用 類名.變量名 調(diào)用)
- 函數(shù)
- 實(shí)例函數(shù)(創(chuàng)建對(duì)象后趴腋,使用 對(duì)象.函數(shù)名 調(diào)用)
- 靜態(tài)函數(shù)(用static修飾淳附,使用 類名.函數(shù)名 調(diào)用)
- 構(gòu)造函數(shù)
- 默認(rèn)構(gòu)造函數(shù)
- 自定義構(gòu)造函數(shù)
- 靜態(tài)構(gòu)造函數(shù)(使用const修飾的構(gòu)造函數(shù))
- 重定向構(gòu)造函數(shù)
- 工廠構(gòu)造函數(shù)
- 變量
- 抽象類
- 變量
- 實(shí)例變量(其子類創(chuàng)建對(duì)象后谍肤,使用 對(duì)象.變量名 調(diào)用)
- 靜態(tài)變量(用static修飾,使用 類名.變量名 調(diào)用)
- 函數(shù)
- 實(shí)例函數(shù)(其子類創(chuàng)建對(duì)象后,使用 對(duì)象.函數(shù)名 調(diào)用)
- 靜態(tài)函數(shù)(用static修飾,使用 類名.函數(shù)名 調(diào)用)
- 抽象函數(shù)(其子類實(shí)現(xiàn)該函數(shù)蠢壹,創(chuàng)建對(duì)象后,使用對(duì)象.函數(shù)名 調(diào)用)
- 不能實(shí)例化(工廠構(gòu)造函數(shù)除外)九巡。
- 變量
Object
-
Object
是所有類的父類图贸。 -
Object
沒有父類。 - 一個(gè)類只能有一個(gè)父類冕广。
- 如果一個(gè)類沒有顯示的用
extends
去繼承一個(gè)類疏日,那么默認(rèn)其繼承的是Object
。
- Dart 是一種面向?qū)ο蟮恼Z言撒汉,并且支持基于mixin的繼承方式沟优。
- Dart 語言中所有的對(duì)象都是某一個(gè)類的實(shí)例,所有的類有同一個(gè)基類--Object。
- 基于mixin的繼承方式具體是指:一個(gè)類可以繼承自多個(gè)父類睬辐。
- 使用
.
來調(diào)用實(shí)例的變量或者方法挠阁。 - 使用
?.
來確認(rèn)前操作數(shù)不為空, 常用來替代. , 避免左邊操作數(shù)為null引發(fā)異常。 - 級(jí)聯(lián)操作符 .. 溯饵, 可以連續(xù)調(diào)用對(duì)象的一些列屬性或函數(shù)侵俗。
- 使用new語句來構(gòu)造一個(gè)類,構(gòu)造函數(shù)的名字可能是
ClassName
丰刊,也可以是ClassName.identifier
隘谣, 例如: - 創(chuàng)建類的實(shí)例,使用new 或const啄巧,new對(duì)應(yīng)的是普通的構(gòu)造函數(shù)寻歧,const對(duì)應(yīng)的是用const形式的構(gòu)造函數(shù)掌栅。
- 使用
runtimeType
屬性,在運(yùn)行中獲取對(duì)象的類型熄求。該方法將返回Type 類型的變量渣玲。 - 在類定義中逗概,所有沒有初始化的變量都會(huì)被初始化為null弟晚。
- 構(gòu)造函數(shù)不能繼承(Constructors aren’t inherited)
- 構(gòu)造函數(shù)不能被繼承,父類中的命名構(gòu)造函數(shù)不能被子類繼承逾苫。如果想要子類也擁有一個(gè)父類一樣名字的構(gòu)造函數(shù)卿城,必須在子類是實(shí)現(xiàn)這個(gè)構(gòu)造函數(shù)。
構(gòu)造函數(shù)(Constructors)
- 沒有返回值(factory構(gòu)造方法有返回值)
- 構(gòu)造函數(shù)名與類名相同
- 默認(rèn)構(gòu)造函數(shù)铅搓,如果類中沒有顯示聲明構(gòu)造函數(shù)瑟押,那么會(huì)默認(rèn)有個(gè)構(gòu)造函數(shù),默認(rèn)構(gòu)造函數(shù)是與類同名且無參數(shù)無返回值的函數(shù)星掰。
class Class01{ //變量 int a; String b; //未聲明構(gòu)造函數(shù) //所以這個(gè)類默認(rèn)有個(gè)構(gòu)造函數(shù) //Class01(){} }
- 自定義構(gòu)造函數(shù)
class Class02{ int a; String b; //自定義的一個(gè)構(gòu)造函數(shù)多望,有兩個(gè)參數(shù) Class02(int a,String c){ this.a = a;//名字沖突時(shí),可使用 this b = b; } } void main(){ var c02 = new Class02(3,"abc"); print(c02.a); } ''' //如果構(gòu)造函數(shù)中的參數(shù)都是給實(shí)例變量賦值的氢烘,那么上面這種情況還可以寫成下面這種方式怀偷,簡化了: class Class02{ int a; String b; //自定義的一個(gè)構(gòu)造函數(shù),有兩個(gè)參數(shù) Class02(this.a,this.b); } void main(){ var c02 = new Class02(3,"abc"); print(c02.a); } ''';
- 命名構(gòu)造函數(shù)播玖,一種可以為類聲明多個(gè)構(gòu)造函數(shù)的方式椎工。注意這里沒有重載的概念,不能聲明只是參數(shù)類型或數(shù)量不同的構(gòu)造函數(shù)蜀踏,使用命名構(gòu)造函數(shù)實(shí)現(xiàn)维蒙。
class Class03{ int a; String b; Class03(int a,String b){ this.a = a; this.b = b; } Class03.fun1(int a){ this.a = a; } Class03.fun2(String b){ this.b = b; } } void main(){ var class03 = new Class03(3, "ccc"); var class04 = new Class03.fun1(4); var class05 = new Class03.fun2("ddd"); }
- 靜態(tài)構(gòu)造函數(shù)
- 類的對(duì)象不會(huì)改變
- 類的變量不會(huì)改變,也就是常量了
- 使用final修飾變量
- 使用const 修飾構(gòu)造方法
- 創(chuàng)建實(shí)例時(shí)果覆,使用const 而不是new
class Class04{ final int a; final String b; const Class04(this.a,this.b); void fun01(){ print("aa"); } } void main(){ var class06 = const Class04(4, "ccc"); class06.fun01(); print(class06.a); }
- 重定向構(gòu)造函數(shù)颅痊,在類的構(gòu)造函數(shù)中,有時(shí)我們只是需要調(diào)用到另一個(gè)構(gòu)造函數(shù)局待。
class Class05{ int a; String b; Class05(int a,String b){ this.a = a; this.b = b; } Class05.fun1(int a){ this.a = a; } Class05.fun2(String b):this.fun1(33);//重定向到fun1 Class05.fun3(String b):this(33,"ddddd");//重定向到構(gòu)造函數(shù) }
- 工廠構(gòu)造函數(shù)
- 工廠構(gòu)造函數(shù)不能用
this
八千。 - 使用
factory
修飾構(gòu)造函數(shù) - 構(gòu)造函數(shù)內(nèi)有返回值,類型是當(dāng)前類或其子類燎猛,此返回值可以是用命名構(gòu) 造函數(shù)創(chuàng)建的恋捆,也可以是緩存中的。
- 使用
new
創(chuàng)建實(shí)例
class Class06{ int a; static Class06 instance ; //這里創(chuàng)建了一個(gè)單例 //這里的構(gòu)造函數(shù)用factory修飾重绷,使用new時(shí)沸停, //不再是創(chuàng)建一個(gè)全新的實(shí)例了,而是通過函數(shù)體內(nèi)return獲取到實(shí)例 factory Class06(int a){ if(instance==null){ instance = new Class06.fun1(a); } return instance; } Class06.fun1(this.a);//注意這里是實(shí)例化當(dāng)前對(duì)象的構(gòu)造方法 } void main(){ var class07 = new Class06(3);//使用new print(class07.a); }
- 工廠構(gòu)造函數(shù)不能用
抽象類
- 使用abstract修飾類昭卓。
- 可定義實(shí)例方法愤钾。
- 可定義抽象方法瘟滨,抽象方法沒有函數(shù)體。
- 抽象類不能實(shí)例化(工廠構(gòu)造函數(shù)除外)能颁。
- 子類繼承抽象類后杂瘸,必須實(shí)現(xiàn)所有抽象方法,除非子類也是抽象類伙菊。
- 只有抽象類能定義抽象方法败玉。
//定義抽象類 abstract class Class09{ void fun01();//定義抽象方法 } //繼承抽象類 class Class10 extends Class09{ @override void fun01() {//實(shí)現(xiàn)抽象方法 print("aaa"); } } void main(){ var c10 = new Class10(); c10.fun01(); }
- 抽象方法
''' Instance , getter 和 setter 方法可以是抽象的镜硕,也就是定義一個(gè)接口运翼, 但是把實(shí)現(xiàn)交給其他的類。要?jiǎng)?chuàng)建一個(gè)抽象方法兴枯,使用分號(hào)(血淌;)代替方法體; '''; abstract class Doer { // ...定義實(shí)例變量和方法... void doSomething(); // 定義一個(gè)抽象方法。 } class EffectiveDoer extends Doer { void doSomething() { // ...提供一個(gè)實(shí)現(xiàn)财剖,所以這里的方法不是抽象的... } }
setters 和 Getters
- 是一種提供對(duì)方法屬性讀和寫的特殊方法悠夯。每個(gè)實(shí)例變量都有一個(gè)隱式的 getter 方法,合適的話可能還會(huì)有 setter 方法躺坟。你可以通過實(shí)現(xiàn) getters 和 setters 來創(chuàng)建附加屬性沦补,也就是直接使用 get 和 set 關(guān)鍵詞:
借助于 getter 和 setter ,你可以直接使用實(shí)例變量瞳氓,并且在不改變客戶代碼的情況下把他們包裝成方法策彤。 - 不論是否顯式地定義了一個(gè) getter,類似增量(++)的操作符匣摘,都能以預(yù)期的方式工作店诗。為了避免產(chǎn)生任何向著不期望的方向的影響,操作符一旦調(diào)用 getter 音榜,就會(huì)把他的值存在臨時(shí)變量里庞瘸。
class Rectangle {
num left;
num top;
num width;
num height;
Rectangle(this.left, this.top, this.width, this.height);
// 定義兩個(gè)計(jì)算屬性: right and bottom.
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
}
main() {
var rect = new Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
靜態(tài)變量和靜態(tài)函數(shù)
- 使用static修飾的變量為靜態(tài)變量。
- 使用static修飾的函數(shù)為靜態(tài)函數(shù)赠叼。
- 靜態(tài)變量和函數(shù)擦囊,使用類名直接調(diào)用。
- 實(shí)例變量和函數(shù)嘴办,使用類的對(duì)象調(diào)用瞬场。
- 靜態(tài)變量和函數(shù),不能訪問實(shí)例變量和函數(shù)涧郊。
- 靜態(tài)函數(shù)內(nèi)贯被,不能使用this。
- 普通類和抽象類都可以定義靜態(tài)變量和函數(shù)
- 只有當(dāng)靜態(tài)變量被使用時(shí)才被初始化。
- 你可以將靜態(tài)方法作為編譯時(shí)常量彤灶。例如看幼,你可以把靜態(tài)方法作為一個(gè)參數(shù)傳遞給靜態(tài)構(gòu)造函數(shù)。
class Class11{
static int a = 3;//靜態(tài)變量
int b = 4;//實(shí)例變量
//靜態(tài)方法
static void fun01(int c){
print(c);
//print(b);//這里報(bào)錯(cuò)幌陕,靜態(tài)方法內(nèi)不能使用實(shí)例變量
}
//實(shí)例方法
void fun02(){
print(b);
}
}
void main(){
var class11 = new Class11();
//實(shí)例變量和函數(shù)
print(class11.b);
class11.fun02();
//調(diào)用靜態(tài)變量和函數(shù)
Class11.fun01(44);
print(Class11.a);
}
枚舉類
- 是一種用來代表一個(gè)固定數(shù)量的常量的特殊類诵姜。
- 使用enum聲明枚舉。
- 每個(gè)枚舉值都有一個(gè)唯一值搏熄。
- 枚舉不能使用new實(shí)例化 棚唆。
- 使用枚舉值 枚舉.枚舉值。
- 你不能在子類中混合或?qū)崿F(xiàn)一個(gè)枚舉搬卒。
'''聲明一個(gè)枚舉類型需要使用關(guān)鍵字 enum :'''瑟俭;
enum Color {
red,
green,
blue
}
'''
在枚舉中每個(gè)值都有一個(gè) index getter 方法翎卓,它返回一個(gè)在枚舉聲明中從 0 開始的位置契邀。
例如,第一個(gè)值索引值為 0 失暴,第二個(gè)值索引值為 1 坯门。
''';
assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);
'''要得到枚舉列表的所有值,可使用枚舉的 values 常量逗扒。''';
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);
'''
你可以在 switch 語句 中使用枚舉古戴。
如果 e 在 switch (e) 是顯式類型的枚舉,那么如果你不處理所有的枚舉值將會(huì)彈出警告:
''';
Color aColor = Color.blue;
switch (aColor) {
case Color.red:
print('Red as roses!');
break;
case Color.green:
print('Green as grass!');
break;
default: // Without this, you see a WARNING.
print(aColor); // 'Color.blue'
}
繼承
使用extends 關(guān)鍵字表示繼承矩肩。
構(gòu)造方法不能被繼承现恼。
使用@override重寫函數(shù)。
如果繼承的是抽象類黍檩,要實(shí)現(xiàn)所有抽象函數(shù)叉袍。
-
繼承抽象類
//定義抽象類 abstract class Parent{ int a = 1; String b = "bb"; void fun1();//定義抽象方法 void fun2(int a,int c){ this.a = a; print(c); } } class Child extends Parent{ String b = "child b";//重寫了父類的屬性 //實(shí)現(xiàn)了父類的抽象函數(shù) @override void fun1() { print(b); } //重寫了父類的函數(shù) @override void fun2(int a, int c) { print(a+c); } } void main(){ var child = new Child(); child.fun1();// child b child.fun2(3, 4); //7 }
-
繼承普通類
- 子類至少定義一個(gè)構(gòu)造函數(shù)調(diào)用父類的任一構(gòu)造函數(shù),使用:super刽酱。
- 子類的每個(gè)構(gòu)造函數(shù)都要繼承父類的任一構(gòu)造函數(shù)喳逛。
- 子類可重寫父類的函數(shù)。
class Fruit{
String name;
int nums;
Fruit(this.name);//定義構(gòu)造函數(shù)
Fruit.num(this.name,this.nums);//定義命名構(gòu)造函數(shù)
Fruit.con(num){//定義命名構(gòu)造函數(shù)
nums = num*2;
}
void fun1(){
print(name);
}
void fun2(){
print(nums);
}
}
class Apple extends Fruit{
String name;
int nums;
int color;
//至少需要定義一個(gè)構(gòu)造函數(shù)調(diào)用父類的任一構(gòu)造函數(shù)
Apple(String name) : super(name);
Apple.con1(this.color,this.name): super.num(name,3);
Apple.con2() : super.con(3){
color = 3;
}
//重寫父類的fun2函數(shù)
@override
void fun2() {
print(color);
super.fun2();//調(diào)用父類的fun2方法
}
//子類自己的方法
void fun3(){
print(nums);
}
}
//使用 extends 創(chuàng)建一個(gè)子類棵里,同時(shí) supper 將指向父類:
class Television {
void turnOn() {
_illuminateDisplay();
_activateIrSensor();
}
// ...
}
class SmartTelevision extends Television {
void turnOn() {
super.turnOn();
_bootNetworkInterface();
_initializeMemory();
_upgradeApps();
}
// ...
}
- 下面是個(gè)關(guān)于重寫 Object 類的方法 noSuchMethod() 的例子,當(dāng)代碼企圖用不存在的方法或?qū)嵗兞繒r(shí)润文,這個(gè)方法會(huì)被調(diào)用。
class A {
// 如果你不重寫 noSuchMethod 方法, 就用一個(gè)不存在的成員殿怜,會(huì)導(dǎo)致NoSuchMethodError 錯(cuò)誤典蝌。
void noSuchMethod(Invocation mirror) {
print('You tried to use a non-existent member:' +
'${mirror.memberName}');
}
}
你可以使用 @override 注釋來表明你重寫了一個(gè)成員。
class A {
@override
void noSuchMethod(Invocation mirror) {
// ...
}
}
'''
如果你用 noSuchMethod() 實(shí)現(xiàn)每一個(gè)可能的 getter 方法头谜,
setter 方法和類的方法骏掀,那么你可以使用 @proxy 標(biāo)注來避免警告。
''
@proxy
class A {
void noSuchMethod(Invocation mirror) {
// ...
}
}
mixins
- mixins 是一種多類層次結(jié)構(gòu)的類的代碼重用。
- 要使用 mixins 砖织,在 with 關(guān)鍵字后面跟一個(gè)或多個(gè) mixin 的名字款侵。用
,
分開 - 要實(shí)現(xiàn) mixin ,就創(chuàng)建一個(gè)繼承 Object 類的子類侧纯,不聲明任何構(gòu)造函數(shù)新锈,不調(diào)用 super 。
class With1 {
String getName() => 'With1';//三個(gè)類都有該方法
String getAge()=> "With1 10" ;//該類獨(dú)有
}
class With2 {
String getName() => 'With2';//三個(gè)類都有該方法
String getColor() => "With2 red";//該類獨(dú)有
int getNum()=> 6;//該類和OtherClass都有
String getFruit()=>"With2 banana";
}
class OtherClass {
String getName() => 'OtherClass';//三個(gè)類都有該方法
int getNum() => 3; //該類和With2都有
int getDesk() => 333;//該類獨(dú)有
String getPhone()=>"OtherClass huawei";//該類和子類
String getFruit()=>"OtherClass apple";
}
class Child1 extends OtherClass with With1 ,With2 {
//重寫父類
@override
String getPhone() {
return "Child1 iphone";
}
@override
String getFruit() {
return "Child1 oriange";
}
}
class Child2 extends OtherClass with With2, With1 {}
void main(){
print("class Child1 extends OtherClass with With1 ,With2 {}");
Child1 c1 = Child1();
//Child1 iphone 重寫了函數(shù)眶熬,調(diào)用時(shí)用的是自身的函數(shù)
print(c1.getPhone());
//Child1 oriange 重寫了函數(shù)妹笆,調(diào)用時(shí)用的是自身的函數(shù)
print(c1.getFruit());
//333 調(diào)用的是OtherClass的函數(shù) With1 With2中沒有同名函數(shù)
print(c1.getDesk());
print(c1.getNum());//6 調(diào)用的是With2中的函數(shù)
print(c1.getAge());//With1 10 調(diào)用的是With1中的函數(shù)
print(c1.getColor());//With2 red 調(diào)用的是With2中的函數(shù)
//With2 調(diào)用的是With2中的函數(shù) With2在聲明順序中更靠后
print(c1.getName());
print("-----------------------");
print("class Child2 extends OtherClass with With2, With1 {}");
Child2 c2 = Child2();
//OtherClass huawei 沒有重寫函數(shù),調(diào)用時(shí)用的是OtherClass的函數(shù)
print(c2.getPhone());
//With2 banana 沒有重寫函數(shù)娜氏,調(diào)用時(shí)用的是With2的函數(shù)
//雖然OtherClass也有拳缠,但With2在聲明順序中更靠后
print(c2.getFruit());
//333 調(diào)用的是OtherClass的函數(shù) With1 With2中沒有同名函數(shù)
print(c2.getDesk());
print(c2.getNum());//6 調(diào)用的是With2中的函數(shù)
print(c2.getAge());//With1 10 調(diào)用的是With1中的函數(shù)
print(c2.getColor());//With2 red 調(diào)用的是With2中的函數(shù)
//With1 調(diào)用的是With1中的函數(shù) With1在聲明順序中更靠后
print(c2.getName());
}
隱式接口
- Z 實(shí)現(xiàn)了類X Y ,那么Z中必須重寫XY中所有的屬性和函數(shù)贸弥。
- 與java不同窟坐,dart中沒有專門定義接口的方式,dart中類即是接口绵疲。
- 一個(gè)類可以實(shí)現(xiàn)多個(gè)接口哲鸳,也就是可以實(shí)現(xiàn)多個(gè)類,用implements盔憨。
- 一個(gè)類只能繼承一個(gè)類徙菠,用extends。
class X {
int x= 19;
void funX(){
print("X-X");
}
}
class Y {
String y = "yyy";
void funY(){
print("Y-Y");
}
}
class Z implements X,Y{
@override
int x=33;
@override
String y="33333";
@override
void funX() {
print("Z-X");
}
@override
void funY() {
print("Z-Y");
}
}