Dart語言學習(十二) Dart面向對象

来源:https://www.cnblogs.com/jukaiit/archive/2020/02/04/12260140.html
-Advertisement-
Play Games

Dart作為一種高級語言,支持面向對象的很多特性,並且支持基於mixin的繼承方式。 基於mixin的繼承方式是指:一個類可以繼承自多個父類,相當於其他語言里的多繼承。 所有的類都有同一個基類Object,這和特性類似於Java、Objective-C 等語言,Java所有的類也都是繼承自Objec ...


Dart作為一種高級語言,支持面向對象的很多特性,並且支持基於mixin的繼承方式。

基於mixin的繼承方式是指:一個類可以繼承自多個父類,相當於其他語言里的多繼承。

所有的類都有同一個基類Object,這和特性類似於Java、Objective-C 等語言,Java所有的類也都是繼承自Object,也就是說一切皆對象。

 

//實例化了一個User類的對象user
var user = new User('Liming',25);
  • 實例化成員變數

Class User{
    String name;//name 成員變數
    int age;//age 成員變數
}

類定義中所有的變數都會隱式的定義setter方法,針對非空的變數會額外增加getter方法。

實例化成員變數請參考如下代碼:

void main(){
    var user = new User();
    user.name = 'Liming';//相當於使用了name的setter方法
    user.age = 25;
}
  • 構造函數

  1.常規的構造函數

構造函數是用來構造當前類的函數,是一種特殊的函數,函數名稱必須要和類名相同才行.

如下代碼為User類添加了一個構造函數,函數里給User類的兩個成員變數初始化了值:

Class User{
    String name;
    int age;
    User(String mName,int mAge){
        this.name = mAge;
        this.age = mAge;
    }
}

this關鍵字指向了當前類的實例

上面的代碼可以簡化為:

Class User{
    String name;
    int age;
    User(this.name,this.age);
}

第一種沒有簡化的構造方法初始化成員變數是在方法體內進行初始化的,

第二種簡化的構造方法初始化成員變數,是在實例化類的時候直接進行賦值初始化的。

  2.命名的構造函數

使用命名構造函數是 從另一類或現有的數據中快速實現構造函數 ,代碼如下所示:

Class User{
    String name;
    int age;
    //普通構造函數
    User(this.name,this.age);

    //命名構造函數
    User.fromJson(Map json){
        name = json['name'];
        age = json['age'];
    }
}

//在實例化類的時候,如果沒有傳參,會預設調用無參數的構造方法
//普通構造函數
var user = new User('張三',25);

//命名構造函數
var user = new User.fromJson(mMapJson);

 

  3.子類的創建

註1:子類在繼承父類的時候,如果在父類中有顯示的提供一個無名、無參的構造函數,不會繼承父類無名有參構造函數和命名構造函數,即:子類只會繼承父類無名無參的構造函數。(程式會給類隱式的生成一個無名、無參的構造函數)

註2:子類在繼承父類的時候,如果在父類中沒有有顯示的提供一個無名、無參的構造函數,子類必須手動調用父類的一個構造函數,在這種情況下,調用的父類的構造函數要放在子類構造函數之後,在子類構造函數體之前,用“:”分隔。

註3:父類的構造函數會在子類的構造函數前調用。

註4:預設情況下,子類只能調用父類無名、無參數的構造函數。

註1和註3:父類中有一個無名、無參的構造函數,子類繼承父類,會預設繼承父類無名、無參的構造函數(即使有其他無名、有參的構造函數或者命名構造函數,子類都不會調用),並且,父類的無名、無參的構造函數會在子類的構造函數之前被調用。

Class Futher {

    //無名、無參的構造函數
    Futher(){
        print('我是父類無名、無參的構造函數');
    }
}

Class Son extends Futher {
    //因為父類有顯式的聲明一個無名、無參的構造函數,所以不用手動調用父類的構造函數。
    Son.fromJson(Map mMapJson){
        print('我是子類的命名構造函數');
    }
}

var son = new Son.fromJson(mMapJson);
//列印結果
//我是父類無名、無參的構造函數
//我是子類的命名構造函

註2:下麵代碼里,子類的命名構造方法寫了兩種方式,第一種是正確的,第二種是錯誤的,有詳細的註釋, 如果有疑問請留言。

Class Futher {

    //無名、無參的構造函數
    Futher.printSth(){
        print('我是父類無名、無參的構造函數');
    }
}

Class Son extends Futher {
    //因為父類沒有有顯式的聲明一個無名、無參的構造函數,所以需要手動的調用父類的構造函數。
    Son.fromJson(Map mMapJson) : super Futher.printSth{
        print('我是子類的命名構造函數');
    }

    //這種寫法會報錯,因為父類中沒有顯示的提供一個無名、無參的構造函數。所以需要像上面那樣,手動調用父類的一個構造函數
    Son.fromJson(Map mMapJson){
        print('我是子類的命名構造函數');
    }
}

  4.構造函數初始化列表

上面在講解常規的構造函數和命名構造函數的時候,示例代碼都有對類中的成員變數進行了初始化,

特點是在構造函數的方法體內進行初始化,初始化成員變數還有另一種方式,就是在構造函數運行前來初始化成員變數。

Class User {
    String name;
    int age;

    User(mName,mAge)
        :name = mName,
        age = mAge{
            // Do Some Thing
        }
}

特點是在構造函數的方法體前(大括弧前面)來初始化成員變數,變數間用“,”分隔。

  • 讀取和寫入對象

get()和set()方法是專門用於讀取和寫入對象的屬性的方法,每一個類的實例,系統都會隱式的包含有get()和set()方法。

例如,定義一個矩形的類,有上、下、左、右:top、bottom、left、right四個成員變數,使用get及set關鍵字分別對right、bottom進行獲取和設置值。代碼如下所示:

Class Rectangle {
    num left;
    num top;
    num width;
    num height;

    Rectangle(this.left,this.top,this.width,this.height);

    num get right => left + width;//獲取righht的值(第一行)

    set right(num value) => left = value - width;//設置right的值,同時left也發生了變化(第二行)

    num get bottom => top + height;//獲取bottom的值(第三行)

    set bottom(num value) => top = value - height;//設置bottom值,同時top也發生了變化(第四行)
}

void main(){
    var rect = new Rectangle(3,4,20,15);//實例化Rectangle,並給類中的4個變數進行初始化賦值

    print('left:'+rect.left.toString());//獲取left的值,並列印 left = 3
    print('right:'+rect.right.toString());//獲取right的值,並列印,這裡執行了Rectangle類中第一行代碼,right = left + width,right = 3+20 = 23
    rect.right = 30;//重新給right進行賦值 right = 30,這裡執行了Rectabgke類中的第二行代碼,將right的值設置為30,並且,將left的值改為30 - 20,left = 30-20 = 10
    print('right的值改為30');
    print('left:'+rect.left.toString());//獲取left的值,並列印,因為上面給right重新賦值的時候,也改變了left的值,所以,此時left = 10
    print('right:'+rect.right.toString());//rect.right = 30將right的值改為了30,所以,right = 30


    print('top:'+rect.top.toString());
    print('bottom:'+rect.bottom.toString());
    rect.bottom = 50;
    print('bottom的值改為50');
    print('top:'+rect.top.toString());
    print('bottom:'+rect.bottom.toString());
}

//列印結果
left:3
right:23
right的值改為30
left:10
right:30
top:4
bottom:19
bottom的值改為50
top:35
bottom:50

上面的示例註釋已經解釋的很清楚了,如果有任何疑問,請留言!!!

這裡我就解釋一下“=>”的作用,在Dart裡面,大家可以簡單的理解為接下來要繼續執行後面的操作。

  • 重運算符載操作

在講解重載運算符前需要先說明Dart裡面的一個關鍵字operator,operator和運算符一起使用,表示一個運算符重載函數,在理解時可以將operator和運算符(如operator+或operator-)視為一個函數名。編寫一個例子方便理解。

Class Vector {
    final int x;
    final int y;
    const Vector(this.x,this.y);

    //重載加號 + (a+b)
    Vector operator + (Vector v){
        return new Vector(x + v.x,y + v.y);
    }
}

void main() {
    //實例化兩個變數
    final result1 = new Vector(10,20);
    final result2 = new Vector(30,40);

    final result = result1 + result2;

    print('result.x = '+result.x.toString()+'',+'result.y = '+result.y.toString());

    //列印結果
    result.x = 40,result.y = 60
}

首先創建了一個Vector類,聲明兩個成員變數x和y還有一個構造方法,在Vector類裡面重載一個加法運算符,重載操作返回Vector對象,接下來在main函數裡面,實例化了兩個Vector變數,兩次操作分別給

x和y進行了賦值,x = 10;y = 20;x = 30;y = 40。然後讓result1和result2這兩個變數相加,看到這裡大家可能會有疑問,兩個對象變數怎麼相加呢?這裡我們的運算符重載就發揮出作用了,實際上,在執行final result = result1 + result2;這行代碼的時候,其實是對象result1調用了"operator +"這個函數,並將result2這個對象當作一個參數傳遞給了這個函數,從而實現了對象result1中的x和對象result2中的x相加,對象result1中的y和對象result2中的y相加的操作,所以最終列印的結果result.x = 40,result.y = 60。

註:對於 Dart 提供的所有操作符,通常只支持對於基本數據類型和標準庫中提供的類的操作,而對於用戶自己定義的類,如果想要通過該操作符實現一些基本操作(比如比較大小,判斷是否相等),就需要用戶自己來定義關於這個操作符的具體實現了。

  •  繼承類

繼承是面向對象編程技術的一塊基石,因為它允許創建分等級層次的類。繼承就是子類繼承父類的特征和行為,使得子類對象具有父類的實例域和方法;或子類從父類繼承方法,使得子類具有父類相同的行為。Dart裡面使用extends關鍵字來實現繼承,super關鍵字來指定父類。

Class Animal {
    void eat(){
        print('動物會吃');
    }

    void run(){
        print('動物會跑');
    }
}

Class Human extends Animal {
    void say(){
        print('人會說');
    }

    void study(){
        print('人會學習');
    }
}

void main(){
    var animal = new Animal();
    animal.eat();
    animal.run();

    value human = new Human();
    human.eat();
    human.run();
    human.say();
    human.study();

    //列印結果
    動物會吃
    動物會跑

    動物會吃
    動物會跑
    人會說
    人會學習
}

 

  • 抽象類

抽象類類似於Java語言中的介面。抽象類里不具體實現方法,只是寫好定義介面,具體實現留著調用的人去實現。抽象類可以使用abstract關鍵字定義類。

  1. 抽象類通過abstract關鍵字來定義。
  2. Dart中的抽象方法不能用abstract聲明,Dart中沒有方法體的方法我們成為抽象方法。
  3. 如果子類繼承了抽象類,就必須實現裡面的抽象方法。
  4. 如果把抽象類當作介面實現的話,就必須得實現抽象類裡面的所有屬性和方法。
  5. 抽象類不能實例化,只有繼承它的子類可以實例化。
abstract class Animal{
    eat();   //抽象方法
    run();  //抽象方法  
    printInfo(){
    print('我是一個抽象類裡面的普通方法');
  }
}

class Dog extends Animal{
    @override
    eat() {
        print('小狗在吃骨頭');
    }

    @override
    run() {
        // TODO: implement run
        print('小狗在跑');
    }  
}
class Cat extends Animal{
    @override
    eat() {
        // TODO: implement eat
        print('小貓在吃老鼠');
    }

    @override
    run() {
        // TODO: implement run
        print('小貓在跑');
    }

}

void main(){
    Dog d=new Dog();
    d.eat();
    d.printInfo();

    Cat c=new Cat();
    c.eat();
    c.printInfo();

    // Animal a=new Animal();   //抽象類沒法直接被實例化
}

 

Dart學習系列文章:https://www.cnblogs.com/jukaiit/category/1636484.html

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • pip install mitmproxy Man In The Middle 原理 mitmproxy工程工具包,主要包含了3個組件 功能一致,交互界面不同 mitmproxy:命令行界面,window不支持 mitmdump:命令行介面,可以對接python腳本,通過腳本實現監聽後的處理,可定製 ...
  • 本次講解函數,由於內容比較多,小編列了個大綱,主要有一下內容: 1. 函數基本語法及特性 2. 函數參數 3.局部變數 4. 返回值 5.嵌套函數 6.遞歸 7.匿名函數 8.高階函數 9.內置函數 1. 函數基本語法及特性 函數的定義:函數是指將一組語句的集合通過一個名字(函數名)封裝起來,要想執 ...
  • 我們都知道,語言嘛,當然是用來溝通交流、傳遞信息的,在人類的世界里,語言的種類非常多,像漢語、英語、日語、法語等等。 所以,我們不妨猜想一下,在電腦的世界里,會不會也是這樣的呢?答案是,的確如此。 為了使電腦能夠理解人的意圖,人類就必須將需解決的問題的思路、方法和手段通過電腦能夠理解的形式告訴... ...
  • 應用 MainModule 正確的方法是將連接組件放置在 MainModule 上, 並將數據集放在窗體或窗體所擁有的 DataModules 上。 MainModule 可以被視為會話的核心。 它是一個特殊用途 DataModule, 它是在每次創建新項目時自動創建並添加到項目中的。 MainMo ...
  • 下圖表示 uniGUI 伺服器的內部結構。 每個 uniGUI 伺服器都有一個ServerModule的副本, 每台伺服器創建一次, 同時根據用戶活動動態創建和銷毀多個Session。 uniGUI Session包含一個稱為MainModule(多個)的專用DataModule , 它為每個Ses ...
  • 在UniGUI的CHM幫助里讀到的。 一定要新建一個其他空白的工程,然後再添加LoginForm LoginForm 是另一種特殊的表單類型, 僅用於登錄目的。 此操作將創建一個與常規窗體外觀相同的空白 LoginForm: LoginForm 是一個名為 TUniLoginForm 的內置類的後代 ...
  • Dubbo是一個遠程調用的框架,對於一個服務提供者,暴露了一個介面供外部消費者調用, 那麼對於提供者自己是否可以調用這個介面,需要什麼特殊處理嗎? 這篇文章就分享下Dubbo關於本地調用的實現機制,以及如何開啟和關閉本地調用。 injvm支持本地調用 使用 Dubbo 本地調用不需做特殊配置,按正常 ...
  • Mixins Mixins(混入功能)相當於多繼承,也就是說可以繼承多個類,使用with關鍵字來實現Mixins的功能。 那麼多個類中有相同的方法時候,會被覆蓋嗎?覆蓋的先後是什麼? class A{ void a(){ print("A.a()..."); } } class B{ void a( ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...