上篇博客我們學(xué)習(xí)了dart中的集合谴麦、動(dòng)態(tài)變量和函數(shù)相關(guān)的內(nèi)容,本篇博客將對(duì)dart的類(lèi)操作亮蒋,異步編程和事件驅(qū)動(dòng)進(jìn)行學(xué)習(xí)
類(lèi)
dart作為一個(gè)純粹的面向?qū)ο蟮恼Z(yǔ)言献幔,類(lèi)的概念自然是極為突出煮寡,我們所熟悉的java語(yǔ)言是個(gè)經(jīng)典的面向?qū)ο缶幊痰恼Z(yǔ)言,dart作為一個(gè)優(yōu)秀的犀呼,集百家之長(zhǎng)的語(yǔ)言幸撕,不僅有java中的類(lèi)的所有優(yōu)秀特性,還在此基礎(chǔ)上做了加強(qiáng)
構(gòu)造函數(shù)
在java中我們常見(jiàn)的構(gòu)造分為無(wú)參構(gòu)造和有參構(gòu)造外臂,并且多個(gè)參數(shù)的構(gòu)造可以重載多個(gè)提供不同的需求坐儿,在參數(shù)比較多的場(chǎng)景下,很麻煩宋光,并且增加了代碼量貌矿,而在dart中由于沒(méi)有重載的概念(函數(shù)也是個(gè)類(lèi)型),所以dart中默認(rèn)的構(gòu)造只允許有一個(gè)罪佳,所以我們按照java的有參構(gòu)造逛漫,dart中我們會(huì)按照如下寫(xiě)法:
///分?jǐn)?shù)類(lèi)
class Fraction{
int numerator;//分子
int denominator;//分母
Fraction(int numerator,int denominator){
this.numerator =numerator;
this.denominator =denominator;
}
}
但是這么寫(xiě),其實(shí)還是復(fù)雜了菇民,形參和實(shí)際的參數(shù)一樣的情況下尽楔,dart可以進(jìn)行簡(jiǎn)化開(kāi)發(fā),如下:
///分?jǐn)?shù)類(lèi)
class Fraction{
int numerator;//分子
int denominator;//分母
Fraction(int numerator,int denominator);//形參和實(shí)參一樣的第练,可直接不寫(xiě)方法體和賦值操作
}
這樣的構(gòu)造的確簡(jiǎn)化了開(kāi)發(fā)阔馋,但是我們開(kāi)發(fā)的時(shí)候可能存在既有無(wú)參構(gòu)造,又需要有參構(gòu)造的情況娇掏,dart不支持方法重載我們又該如何呢呕寝?當(dāng)然,我們有兩種方案實(shí)現(xiàn)婴梧,還記得我們上篇博客學(xué)習(xí)了dart的可選命名參數(shù)和可選位置參數(shù)嗎下梢?構(gòu)造函數(shù)完全可以利用該特性完成構(gòu)造
///分?jǐn)?shù)類(lèi)
class Fraction{
int numerator;//分子
int denominator;//分母
Fraction({int numerator,int denominator});//將參數(shù)使用{}包裹,這樣構(gòu)造的時(shí)候可以選擇性的傳遞塞蹭,也可以完全不傳
}
除了可選參數(shù)列表以外孽江,dart還提供了一個(gè)新的概念--命名構(gòu)造函數(shù),即可以指定一個(gè)指定名稱(chēng)的函數(shù)作為構(gòu)造番电,使用如下:
///分?jǐn)?shù)類(lèi)
class Fraction{
int numerator;//分子
int denominator;//分母
Fraction.numerator(int numerator);//指定numerator名稱(chēng)的函數(shù)為構(gòu)造岗屏,可以很清晰的看出來(lái)構(gòu)造是專(zhuān)門(mén)用來(lái)設(shè)置分子的
Fraction.denominator(int denominator);//指定denominator名稱(chēng)的函數(shù)為構(gòu)造,可以很清晰的看出來(lái)構(gòu)造是專(zhuān)門(mén)用來(lái)設(shè)置分母的
_Fraction(){}//還記得剛學(xué)dart的時(shí)候那幾點(diǎn)注意嗎漱办?dart中沒(méi)有公共私有的關(guān)鍵字这刷,如果需要私有化,前面加個(gè)_修飾自動(dòng)編譯為私有屬性/私有方法娩井,也就是說(shuō)當(dāng)前的分?jǐn)?shù)類(lèi)的默認(rèn)構(gòu)造變成私有化暇屋,無(wú)法直接通過(guò)該方法創(chuàng)建
//可以根據(jù)_私有的特性很方便的實(shí)現(xiàn)單例模式
Fraction _newinstance(){
if(null == _instance){
_instance = _Fraction();
}
return _instance;
}
}
初始化列表
在dart構(gòu)造的時(shí)候,我們還可以使用dart提供的快捷方式可以在構(gòu)建的時(shí)候初始化變量,這點(diǎn)和c++一樣洞辣,為:
xxx.函數(shù)名():Filed1=xxx,Filed2=xxx.....;
///分?jǐn)?shù)類(lèi)
class Fraction{
int numerator;//分子
int denominator;//分母
Fraction.numerator(int numerator);//指定numerator名稱(chēng)的函數(shù)為構(gòu)造咐刨,可以很清晰的看出來(lái)構(gòu)造是專(zhuān)門(mén)用來(lái)設(shè)置分子的
Fraction.denominator(int denominator);//指定denominator名稱(chēng)的函數(shù)為構(gòu)造昙衅,可以很清晰的看出來(lái)構(gòu)造是專(zhuān)門(mén)用來(lái)設(shè)置分母的
Fraction.init():numerator=1,denominator=0;//在構(gòu)造函數(shù)后直接:拼接屬性賦值操作,可以在構(gòu)造的時(shí)候初始化一些參數(shù)值,對(duì)于一些final修飾的屬性初始化以后固定值不會(huì)在變定鸟,非常合適
}
重定向構(gòu)造函數(shù)
dart中不僅提供了初始化列表的操作绒尊,還提供了構(gòu)造的重定向操作,語(yǔ)法和初始化列表一樣仔粥,只是將其他的構(gòu)造當(dāng)成屬性回調(diào)
///分?jǐn)?shù)類(lèi)
class Fraction{
int numerator;//分子
int denominator;//分母
Fraction.numerator(int numerator);//指定numerator名稱(chēng)的函數(shù)為構(gòu)造,可以很清晰的看出來(lái)構(gòu)造是專(zhuān)門(mén)用來(lái)設(shè)置分子的
Fraction.denominator(int denominator);//指定denominator名稱(chēng)的函數(shù)為構(gòu)造蟹但,可以很清晰的看出來(lái)構(gòu)造是專(zhuān)門(mén)用來(lái)設(shè)置分母的
Fraction.init():numerator=1,denominator=0;
Fraction.forword():this.numerator(1);//這里回調(diào)當(dāng)前的分子構(gòu)造函數(shù)躯泰,即我們可以公開(kāi)一個(gè)構(gòu)造方法,內(nèi)部進(jìn)行邏輯操作华糖,不同的業(yè)務(wù)進(jìn)入不同的內(nèi)部構(gòu)造初始化操作
}
常量構(gòu)造函數(shù)
如果你的類(lèi)的屬性都是固定不變的麦向,dart提供了一個(gè)常量構(gòu)造函數(shù),使用const修飾構(gòu)造客叉,并且所有的屬性需要使用final修飾诵竭,這樣做的好處是,當(dāng)你調(diào)用多個(gè)一樣參數(shù)的常量構(gòu)造的時(shí)候兼搏,你獲取的是同一個(gè)對(duì)象卵慰,從而節(jié)省內(nèi)存開(kāi)銷(xiāo)和運(yùn)行效率,需要注意的是,這里的使用常量構(gòu)造佛呻,不允許出現(xiàn)其他的構(gòu)造裳朋,并且只能是公共的默認(rèn)有參構(gòu)造,所有的屬性都必須是final修飾吓著,并且傳遞的參數(shù)中所有的參數(shù)都需要傳遞
class Fraction{
final int numerator;//分子
final int denominator;//分母
const Fraction(this.numerator,this.denominator);
}
工廠構(gòu)造函數(shù)
在dart中除了以上幾種構(gòu)造以外鲤嫡,還提供了一種工廠構(gòu)造函數(shù),使用工廠構(gòu)造函數(shù)的好處是在這里不必創(chuàng)建新的實(shí)例绑莺,可以選擇從緩存中獲取一個(gè)實(shí)例并且返回暖眼,甚至可以返回一個(gè)指定的子類(lèi)實(shí)例,這里可以理解為java設(shè)計(jì)模式中的工廠設(shè)計(jì)模式的變種升級(jí)版本纺裁,但是需要注意的是使用工廠構(gòu)造函數(shù)诫肠,必須使用factory關(guān)鍵字修飾構(gòu)造方法,并且在工廠構(gòu)造中不允許使用this關(guān)鍵字
class Fraction{
static final Map<String,Fraction> cacheMap = new Map<String,Fraction>();
factory Fraction(String name){
if(cacheMap.containsKey(name)){
return cacheMap[name];
}else{
cacheMap[name] = Fraction._newInstance();
return cacheMap[name];
}
}
Fraction._newInstance();
}
Get/Set
在java中对扶,我們一般會(huì)對(duì)實(shí)體進(jìn)行封裝区赵,提供set和get方法,在dart中同樣支持get/set浪南,但是需要注意的是如果我們的屬性是公開(kāi)的笼才,默認(rèn)調(diào)用xxx.Filed = xxx或者var xxx = xxx.Filed這樣的獲取值和設(shè)置值的操作的時(shí)候,調(diào)用的就是dart默認(rèn)的get和set方法络凿,也就是說(shuō)在dart中骡送,默認(rèn)是有g(shù)et和set的昂羡,我們可以不用重寫(xiě)方法,但是如果我們將所有的屬性置為_(kāi)修飾的私有化摔踱,這個(gè)時(shí)候虐先,因?yàn)轭?lèi)外無(wú)法訪問(wèn)到這個(gè)屬性,默認(rèn)的get和set就失效了派敷,我們就需要手動(dòng)設(shè)置方法去提供對(duì)應(yīng)的set/get方法(由于在flutter中蛹批,禁止使用反射,所以目前為止不會(huì)出現(xiàn)和java一樣通用方法名getxxx篮愉,setXXX的情況腐芍,dart的get/set方法名可以任意取,但是博主建議還是按照規(guī)范的習(xí)慣來(lái)開(kāi)發(fā)),需要注意的一點(diǎn)是在set和get方法中不要調(diào)用自身方法试躏,dart中有層級(jí)樹(shù)的概念猪勇,遞歸調(diào)用會(huì)導(dǎo)致Stack Overflow異常
class Fraction{
int _numerator;
int _denominator;
void setNumerator(int numerator){
this._numerator = numerator;
}
}
//在別的dart文件中引用,當(dāng)前文件引用肯定是可以找到私有屬性的,下面是其他dart文件的代碼
import 'class_test.dart';
void main(){
Fraction fraction = new Fraction();
//fraction.numerator = 1;//找不到默認(rèn)的set方法了颠蕴,這里會(huì)報(bào)錯(cuò)
fraction.setNumerator(1);//只能使用自己設(shè)置的set
}
可復(fù)寫(xiě)操作符運(yùn)算
在dart中泣刹,類(lèi)不僅有基本的概念和簡(jiǎn)化的寫(xiě)法,并且提供了一些增強(qiáng)的屬性犀被,比如在dart中椅您,我們可以復(fù)寫(xiě)基本的運(yùn)算符運(yùn)算規(guī)則(不能改寫(xiě)運(yùn)算符自身的優(yōu)先級(jí)),使得我們可以做到任意類(lèi)之間可以進(jìn)行基本運(yùn)算符操作寡键,比如兩個(gè)對(duì)象之間進(jìn)行加減乘除運(yùn)算襟沮,再比如我們常用的list內(nèi)部就重寫(xiě)了[]運(yùn)算符,目前為止昌腰,dart支持可以重寫(xiě)的運(yùn)算符如下:
| <
| +
| |
| []
|
| ---- | ---- | ---- | ----- |
| >
| /
| ^
| []=
|
| <=
| ~/
| &
| ~
|
| >=
| *
| <<
| ==
|
| –
| %
| >>
| |
接下來(lái)我們來(lái)通過(guò)重寫(xiě)基本的運(yùn)算符开伏,根據(jù)我們的案例分?jǐn)?shù)類(lèi),實(shí)現(xiàn)一個(gè)基本的分子分母相加相乘并且盡量簡(jiǎn)化輸出結(jié)果的案例代碼:
分?jǐn)?shù)類(lèi)fraction_class.dart的代碼如下:
/**
* 分?jǐn)?shù)類(lèi)
*/
class Fraction{
num numerator;//分子
num denominator;
static const ISNULL_EXCEPTION = "異常:分子/分母不可以為null";
static const ISNOTZERO_EXCEPTION = "異常:分母不可以為0";
static const NULL_OPERATION_EXCEPTION = "異常:不可以和null進(jìn)行運(yùn)算";
Fraction(num numerator,num denominator){
if(null == numerator || null == denominator){
throw ISNULL_EXCEPTION;
}
if(denominator == 0){
throw ISNOTZERO_EXCEPTION;
}
this.numerator = numerator;
this.denominator = denominator;
}
@override
String toString() {
return "分子為:${numerator},分母為:${denominator}";
}
/**
* 分?jǐn)?shù)相加方法:首先先找分母之間的最小公倍數(shù)遭商,計(jì)算出分子轉(zhuǎn)換成最小公倍數(shù)以后相加的結(jié)果固灵,最后將最后的結(jié)果進(jìn)行約分計(jì)算
*/
Object operator +(Fraction fraction){
if(null == fraction){
throw NULL_OPERATION_EXCEPTION;
}
//加法運(yùn)算需要找分母的最小公倍數(shù)轉(zhuǎn)換后進(jìn)行計(jì)算
FracionCompute fractionCompute = new FracionCompute();
int minCommonMultiple = fractionCompute.minCommonMultiple(this.denominator,fraction.denominator);
//計(jì)算一下分子分別需要乘以多少倍
int newNumerator = ((minCommonMultiple / (denominator.toInt())).toInt()) * (numerator.toInt());
//傳遞來(lái)進(jìn)行計(jì)算的分?jǐn)?shù)分子分母轉(zhuǎn)換為最小公倍數(shù)
int newNumerator2 = ((minCommonMultiple / (fraction.denominator.toInt())).toInt()) * (fraction.numerator.toInt());
//分子相加
int plusNumerator = (newNumerator + newNumerator2);
//約分操作
return fractionCompute.reductionOfFraction(plusNumerator, minCommonMultiple);
}
/**
* 分?jǐn)?shù)相乘方法:
* 代碼計(jì)算的話就不需要先約分,計(jì)算完畢再去約分(只有人計(jì)算的時(shí)候會(huì)先把分子分母約分再去算乘法)
*/
Object operator *(Fraction fraction){
if(null == fraction){
throw NULL_OPERATION_EXCEPTION;
}
//獲取第一個(gè)分子和第二個(gè)分母的最大公約數(shù)
FracionCompute fractionCompute = new FracionCompute();
//轉(zhuǎn)換后的結(jié)果再去約分一次劫流,防止相乘的兩個(gè)分?jǐn)?shù)為5/5 * 6/6這種無(wú)聊的分?jǐn)?shù)巫玻,結(jié)果為整數(shù)應(yīng)該返回整數(shù)
return fractionCompute.reductionOfFraction((numerator * fraction.numerator).toInt(), (denominator * fraction.denominator).toInt());
}
}
用來(lái)計(jì)算函數(shù)的FracionCompute類(lèi)--fracion_compute.dart文件代碼如下:
import 'fraction_class.dart';
/**
* 分?jǐn)?shù)計(jì)算類(lèi)
*/
class FracionCompute{
/**
* 求最大公約數(shù) 先比較兩個(gè)數(shù)是不是一樣的,一樣的直接返回祠汇,不一樣的話,比較大的分母是否為另一個(gè)的倍數(shù)仍秤,如果是那么返回最小的那個(gè)值,
* 如果都不是,就使用窮舉找到兩個(gè)都能整除的最大公約數(shù),需要注意1和這這兩個(gè)值中相對(duì)較小的值本身
* 如果比較小的值直接就能滿足可很,那么就是比較小的那個(gè)值為最大公約數(shù)诗力,如果一直窮舉到2還不滿足,那么他們就是沒(méi)有公約數(shù)我抠,返回1
*/
int maxCommonMeasure(num number,num number2){
if(number == number2){
return number;
}
int max = number.toInt();
if(number.toInt() > number2.toInt()){
max = number2.toInt();
}
for(int i = max;i > 1;i --){
if(number.toInt() % i == 0 && number2.toInt() % i == 0){
return i;
}
}
return 1;
}
/**
*求最小公倍數(shù) 先比較兩個(gè)數(shù)是不是一樣的苇本,一樣的直接返回袜茧,不一樣的話,判斷是否存在0,
*比較大的分母是否為另一個(gè)的倍數(shù)瓣窄,如果是那么返回最大那個(gè)值笛厦,如果都不是,就使用窮舉找到兩個(gè)都能整除的最小公倍數(shù)俺夕,
*這個(gè)值從比較大的值開(kāi)始裳凸,到兩個(gè)值的乘積結(jié)束,
*每次遞加比較大的那個(gè)值劝贸,可以最快求出來(lái)兩者公倍數(shù)
*/
int minCommonMultiple(num number,num number2){
if(number.toInt() == number2.toInt()){
return number.toInt();
}
int temp = number.toInt();
if(number.toInt() < number2.toInt()){
temp = number2.toInt();
}
for(int i = temp;i <= number.toInt() * number2.toInt();i = i + temp){
if(i % number.toInt() == 0 && i % number2.toInt() == 0){
return i;
}
}
}
/**
* 約分方法登舞,根據(jù)規(guī)則計(jì)算,如果分子/分母剛好整除那么就是返回int類(lèi)型的結(jié)果悬荣,如果不是整除那么就返回分?jǐn)?shù)類(lèi)型的最簡(jiǎn)單約分模式
*/
Object reductionOfFraction(int numerator,int denominator){
if(numerator == denominator){
return 1;
}
//如果分子大于分母
if(numerator > denominator){
if(numerator % denominator == 0){
return (numerator / denominator).toInt();
}
}else{
//分子小于分母,約分計(jì)算
if(denominator % numerator == 0){
return new Fraction(1,(denominator / numerator).toInt());
}
}
//還要考慮分子和分母有公約數(shù)的情況疙剑,需要計(jì)算一次最大公約數(shù)氯迂,然后除以最大公約數(shù)
int max = maxCommonMeasure(numerator,denominator);
return new Fraction((numerator / max).toInt(), (denominator / max).toInt());
}
}
接下來(lái)就是測(cè)試的main方法了:
void main(){
try{
Fraction fraction = new Fraction(5,15);
Fraction fraction2 = new Fraction(2,6);
var object = fraction + fraction2;
print(object); //輸出-->分子為:2,分母為:3
//分?jǐn)?shù)相乘
var object2 = fraction * fraction2;
print(object2);//輸出-->分子為:1,分母為:9
//創(chuàng)建個(gè)異常的分?jǐn)?shù),分母為0
Fraction fraction3 = new Fraction(0,0);
}catch(e){
print(e);//輸出-->異常:分母不可以為0
}
}
抽象類(lèi)和接口
做過(guò)java開(kāi)發(fā)的都知道言缤,java基于c++的面向?qū)ο筮M(jìn)行了細(xì)分嚼蚀,有了抽象類(lèi)和接口的概念,dart語(yǔ)言同樣也支持這些特性管挟,當(dāng)然需要注意的一點(diǎn)是dart中不存在接口的概念轿曙,在dart中只有類(lèi),沒(méi)有接口僻孝,但是dart給了實(shí)現(xiàn)類(lèi)的方法导帝,用來(lái)替代接口
抽象類(lèi)
在dart的類(lèi)定義中可以使用abstract來(lái)修飾class,這樣的類(lèi)即為抽象類(lèi)穿铆,同樣您单,dart的抽象類(lèi)可以抽象方法和普通實(shí)現(xiàn)方法共存,但是我們需要注意的一點(diǎn)是荞雏,dart中的抽象方法沒(méi)有abstract關(guān)鍵字修飾虐秦,僅僅是無(wú)方法體的方法
abstract class Parent {
String name;
void printName(); //抽象方法,不需要在方法前聲明 abstract
}
同樣的dart中的抽象類(lèi)和java一樣凤优,不可以直接實(shí)例化悦陋,但是在dart中你可以給抽象類(lèi)提供一個(gè)工廠方法,按照指定的業(yè)務(wù)邏輯返回對(duì)應(yīng)的子類(lèi)的實(shí)例
abstract class Parent {
String name;
//默認(rèn)構(gòu)造方法
Parent(this.name);
//工廠方法返回Child實(shí)例
factory Parent.test(String name){
return new Child(name);
}
void printName();
}
// extends 繼承抽象類(lèi)
class Child extends Parent{
Child(String name) : super(name);
@override
void printName() {
print(name);
}
}
void main() {
var p = Parent.test("Lance");
print(p.runtimeType); //輸出實(shí)際類(lèi)型 Child,runtimeType屬性可以輸出對(duì)應(yīng)的class類(lèi)型
p.printName();
}
接口與實(shí)現(xiàn)
熟悉java開(kāi)發(fā)的都知道筑辨,在java中有接口這個(gè)概念俺驶,并且和申明class的方式一樣,只是區(qū)別在于修飾的關(guān)鍵字為interface棍辕,并且在接口中只能有抽象的方法痒钝,不允許出現(xiàn)任何方法體的普通實(shí)現(xiàn)方法秉颗,而在dart中并沒(méi)有interface關(guān)鍵字,Dart中每個(gè)類(lèi)都隱式的定義了一個(gè)包含所有實(shí)例成員的接口送矩,并且這個(gè)類(lèi)實(shí)現(xiàn)了這個(gè)接口蚕甥,如果我們需要A類(lèi)支持B類(lèi)的方法的話,我們可以選擇繼承栋荸,但是我們可能不想繼承B類(lèi)菇怀,或者已經(jīng)繼承了其他類(lèi),我們可以選擇實(shí)現(xiàn)B類(lèi)隱式接口
class Listener{
void onComplete(){}
void onFailure(){}
}
class MyListsner implements Listener{
MyListsner(){
}
@override
void onComplete() {
//代碼體實(shí)現(xiàn)
}
@override
void onFailure() {
//代碼體實(shí)現(xiàn)
}
}
與繼承的區(qū)別在于:
1晌块、單繼承爱沟,多實(shí)現(xiàn)(這點(diǎn)和java一樣,和c++的多繼承不一樣)匆背。
2呼伸、繼承可以有選擇的重寫(xiě)父類(lèi)方法并且可以使用super
,實(shí)現(xiàn)強(qiáng)制重新定義接口所有成員
默認(rèn)可調(diào)用的類(lèi)(彩蛋特性)
在dart新版本中钝尸,加入了一個(gè)很有趣的彩蛋式的特性括享,即如果某個(gè)類(lèi)中實(shí)現(xiàn)了call()函數(shù),我們可以直接使用珍促,不需要調(diào)用這個(gè)函數(shù)名铃辖,默認(rèn)就是調(diào)用call函數(shù),使用如下:
class Listener{
void call(){
print('默認(rèn)調(diào)用了call函數(shù)!!!');
}
}
void main(){
Listener listener = new Listener();
listener();//這里不僅不會(huì)報(bào)錯(cuò)猪叙,反而輸出了call的結(jié)果-->默認(rèn)調(diào)用了call函數(shù)!!!
}
混入Mixins
dart中新支持了一個(gè)類(lèi)的特性娇斩,即為mixins(混入),按照dart官方的說(shuō)明穴翩,這個(gè)混入的特性犬第,可以同時(shí)混入多個(gè)類(lèi)的屬性和方法,(博主這里測(cè)試了很多次芒帕,特性和繼承沒(méi)什么區(qū)別瓶殃,也可以使用super.xxx方法調(diào)用父類(lèi)的方法,需要注意的一點(diǎn)是副签,繼承和混入是可以兼容同時(shí)存在的遥椿,但是實(shí)現(xiàn)和混入?yún)s不可以同時(shí)出現(xiàn),可以看出來(lái)混入的特性是用來(lái)彌補(bǔ)接口和繼承的不足淆储,繼承只能單繼承冠场,而接口無(wú)法復(fù)用實(shí)現(xiàn),mixins卻可以多混入并且能利用到混入類(lèi)的具體實(shí)現(xiàn))本砰,使用混入只需要在類(lèi)上使用with關(guān)鍵字:
abstract class A{
void open(){
print('默認(rèn)調(diào)用了A的open!!!');
}
}
abstract class B{
void close(){
print("調(diào)用了B的close");
}
}
//接口類(lèi)
class Listener{
void onListener(){}
}
//這里implements和with同時(shí)出現(xiàn)的時(shí)候碴裙,編譯器就會(huì)報(bào)錯(cuò),明確告知使用with以后不能存在implements關(guān)鍵字
class C extends A implements Listener with B{
}
//使用混入就可以隨便使用繼承,并且默認(rèn)實(shí)現(xiàn)其他類(lèi)舔株,不需要重寫(xiě)該方法
class D extends A with B,Listener{}
class E extends A implements B{
@override
void close() {
//這里我們可能也只是想默認(rèn)實(shí)現(xiàn)B的莺琳,并不需要復(fù)寫(xiě),但是只是繼承和實(shí)現(xiàn)的話载慈,我們只能選擇默認(rèn)再去實(shí)現(xiàn)一次
//print("調(diào)用了B的close");
}
}