(四)flutter入門(mén)之dart中的類(lèi)操作詳解

上篇博客我們學(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");
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惭等,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子办铡,更是在濱河造成了極大的恐慌辞做,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寡具,死亡現(xiàn)場(chǎng)離奇詭異丛晦,居然都是意外死亡筛璧,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)浦旱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)您访,“玉大人透硝,你說(shuō)我怎么就攤上這事桦锄√闹冢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵粪般,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我污桦,道長(zhǎng)亩歹,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任凡橱,我火速辦了婚禮小作,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘稼钩。我一直安慰自己顾稀,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布坝撑。 她就那樣靜靜地躺著静秆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪巡李。 梳的紋絲不亂的頭發(fā)上抚笔,一...
    開(kāi)封第一講書(shū)人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音侨拦,去河邊找鬼殊橙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的膨蛮。 我是一名探鬼主播叠纹,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼敞葛!你這毒婦竟也來(lái)了誉察?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤制肮,失蹤者是張志新(化名)和其女友劉穎冒窍,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體豺鼻,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡综液,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了儒飒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谬莹。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖桩了,靈堂內(nèi)的尸體忽然破棺而出附帽,到底是詐尸還是另有隱情,我是刑警寧澤井誉,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布蕉扮,位于F島的核電站,受9級(jí)特大地震影響颗圣,放射性物質(zhì)發(fā)生泄漏喳钟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一在岂、第九天 我趴在偏房一處隱蔽的房頂上張望奔则。 院中可真熱鬧,春花似錦蔽午、人聲如沸易茬。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)抽莱。三九已至,卻和暖如春骄恶,著一層夾襖步出監(jiān)牢的瞬間岸蜗,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工叠蝇, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留璃岳,地道東北人年缎。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像铃慷,于是被迫代替她去往敵國(guó)和親单芜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容