Dart基礎(四)

級別: ★☆☆☆☆
標籤:「Flutter 」「Dart」「Dart class」「Dart mixin」「Dart override」
做者: WYW
審校: QiShare團隊php


前言
筆者在以前已經寫了3篇Dart的基礎文章了。
Dart 基礎 (一)
Dart 基礎 (二)
Dart 基礎 (三)git

筆者在本文中主要會分享:類、實例變量、構造方法、命名構造方法、實例方法、靜態變量、靜態方法、set、get 方法、extendsimplementsmixinabstractoverride相關的內容。github

1.類

下邊筆者先以Point 類爲例,分享下關於實例變量構造方法命名構造方法實例方法靜態方法靜態變量set get方法 的內容。算法

Dart 是一種面向對象的編程語言,同時支持基於 mixin 的繼承機制。mixin相關的內容會在下文解釋。每一個對象都是一個類的實例,全部的類都繼承於 Object。 基於 Mixin 的繼承 意味着每一個類(Object 除外) 都只有一個超類,一個類的代碼能夠在其餘 多個類繼承中重複使用。express

使用 new 關鍵字和構造方法來建立新的對象。 構造方法名字能夠爲 ClassName 或者 ClassName.identifier。 在Dart2.0的時候,建立新的對象的時候,new 關鍵字是可選的。當前Dart最新版本是2.4.0,2019-06-27 Dart開發團隊發佈2.4.0版本Dart。 Dart change log編程

1.1 實例變量json

class Point {
  
  // 實例變量
  num x;
  num y;
}
複製代碼

1.2 構造方法:構造方法 定義一個和類名同樣的方法數組

// 構造方法 定義一個和類名同樣的方法
  Point(num x, num y) {
    // this 關鍵字指當前的實例
    this.x = x;
    this.y = y;
  }
  
  // 因爲把構造方法參數賦值給實例變量的場景太常見了, Dart 提供了一個語法糖來簡化這個操做
  // Point(this.x, this.y);
複製代碼

1.3 命名構造方法bash

// 命名構造方法
  Point.fromJson(Map json) {
    // 只有當名字衝突的時候才使用 this。不然的話, Dart 代碼風格樣式推薦忽略 this。
    x = json['x'];
    y = json['y'];
  }

  Point.namedConstructor(Map json){
    x = json['x'];
    y = json['y'];
  }

複製代碼

命名構造方法使用場景有:模型類中解析數據場景。微信

舉個簡單例子:如返回一個列表數據的狀況,返回數據多是是一個包着多個字典的數組,那麼,處理相應數據的時候,須要對數據進行相應的解析。解析的過程就可能用到命名構造方法。把一個個字典當作實例,提取出來。

[
	{
		"name":"QiShare1",
		"age":"1"
	},
	{
		"name":"QiShare2",
		"age":"1"
	},
	{
		"name":"QiShare3",
		"age":"1"
	},
	{
		"name":"QiShare4",
		"age":"1"
	},
	{
		"name":"QiShare5",
		"age":"1"
	},
	{
		"name":"QiShare6",
		"age":"1"
	},
	{
		"name":"QiShare7",
		"age":"1"
	},
]
複製代碼

1.4 實例方法

// 實例方法
  num distanceTo(Point other) {
    var dx = x - other.x;
    var dy = y - other.y;
    return sqrt(dx*dx + dy*dy);
  }
複製代碼

1.5 靜態方法

使用static關鍵字修飾的方法爲靜態方法,至關於類方法。使用類名能夠直接調用。

// 靜態方法
  static num distanceBetween(Point a, Point b) {
    var dx = a.x - b.x;
    var dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
  }
複製代碼
void classDemo() {

    var jsonData = jsonDecode('{"x":2, "y":2}');
    // Create a Point using Point().
    var p1 = new Point(1, 1);
    print('p1點x座標:${p1.x}');
    print('p1點y座標:${p1.y}');

    // Create a Point using Point.fromJson().
    var p2 = new Point.fromJson(jsonData);
    print('p2點x座標:${p2.x}');
    print('p2點y座標:${p2.y}');

    num distance = p2.distanceTo(p1);
    print('p1到p2的距離: $distance');

    Map jsonData3 = {
      'x': 3,
      'y': 3,
    };

    Point p3 = Point.namedConstructor(jsonData3);
    print('p3點x座標:${p3.x}');
    print('p3點y座標:${p3.y}');
    
    num distance12 = Point.distanceBetween(p1, p2);
    print('p1和p2之間的距離 $distance12');
    
    }
    
複製代碼

輸出內容

flutter: p1點x座標:1
flutter: p1點y座標:1
flutter: p2點x座標:2
flutter: p2點y座標:2
flutter: p1到p2的距離: 1.4142135623730951
flutter: p3點x座標:3
flutter: p3點y座標:3
flutter: p1和p2之間的距離 1.4142135623730951

複製代碼

1.6 靜態變量

靜態變量對於類級別的狀態是很是有用的,筆者對這句話的理解是:靜態變量能夠由類名直接調用。

class Color {
  static const red =
      const Color('red'); // A constant static variable.
  final String name;      // An instance variable.
  const Color(this.name); // A constant constructor.
}
複製代碼

使用方式

String colorName = Color.red.name;
    print('colorName:$colorName');
複製代碼

輸出內容

colorName:red`
複製代碼

1.7 set get 方法

下邊筆者舉了一個類Rectangle的left、top、width、height的Set、Get方法的例子。

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

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

  // Define two calculated properties: 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;
}

複製代碼

使用方式

Rectangle rectangel = Rectangle(0, 0, 375, 667);
    print('rectangel.left:');
    print(rectangel.left);
    print('rectangel.right:');
    print(rectangel.right);
    print('rectangel.width:');
    print(rectangel.width);
    print('rectangel.height:');
    print(rectangel.height);
    print('rectangel.right:');
    print(rectangel.right);
    print('rectangel.bottom:');
    print(rectangel.bottom);

複製代碼

輸出結果:

flutter: rectangel.left:
flutter: 0
flutter: rectangel.right:
flutter: 375
flutter: rectangel.width:
flutter: 375
flutter: rectangel.height:
flutter: 667
flutter: rectangel.right:
flutter: 375
flutter: rectangel.bottom:
flutter: 667
複製代碼

2. extends 與 implements

extends

關鍵字extends 用於繼承父類的實例變量及方法等。Dart 只支持單繼承。

implements

Every class implicitly defines an interface containing all the instance members of the class and of any interfaces it implements. If you want to create a class A that supports class B’s API without inheriting B’s implementation, class A should implement the B interface.

每一個類都隱式地聲明瞭一個包含全部的實例變量和類已經實現的接口。
若是你想建立一個類A,沒有繼承類B,可是類A可訪問類B的API,那麼類A 應該實現類B的接口。
上邊的內容,結合着下邊的例子,筆者的理解是:Chicken隱式地聲明瞭Animal 的實例變量,和類Animal 已經實現的方法。Chicken支持在沒有繼承類Animal的狀況下,可訪問類B的API。
一個類能夠implements 多個類的API,因此implements算是一種變向實現多繼承的方式。

class Animal {
  String name;
  void ability() {
    print('Animal 的能力');
  }
}

class Bird extends Animal {
  void ability(){
    print('bird can fly');
  }
}

class Fish extends Animal {
  void ability(){
    print('fish can swim');
  }
}

class Dog extends Animal {
  void ability(){
    print('dog can bark');
  }
}

class Chicken implements Animal {
  String name;
  void ability() {
    print('chicken can lay eggs');
  }
}

複製代碼

調用如上代碼的方式及相應輸出結果以下:

Dog dog = Dog();
    dog.ability();
    Fish fish = Fish();
    fish.ability();
    Bird bird = Bird();
    bird.ability();
    Chicken chicken = Chicken();
    chicken.ability();
    
    

// 輸出結果:
flutter: dog can bark
flutter: fish can swim
flutter: bird can fly
flutter: chicken can lay eggs
複製代碼

3. mixin

Mixins 是一種在多類繼承中重用一個類代碼的方法。筆者的理解是,mixin至關因而一個工具類,使用 with 關鍵字使用了mixin的類,就能夠使用mixin中的代碼。

Mixins are a way of reusing a class’s code in multiple class hierarchies.

To use a mixin, use the with keyword followed by one or more mixin names. The following example shows two classes that use mixins:

Mixin 是一種在多個類中重用某些代碼的方式。 使用mixin ,需使用 with 關鍵字,with後邊跟mixin的名,with 後邊能夠跟多個mixin名字,及能夠同時使用多個mixin中的代碼。下邊筆者舉了一個開發者學習基礎語言的例子。

筆者定義了一個Developer的mixin,若是是iOS 開發者須要先學習C語言基礎,若是是Android 開發者,須要先學習Java語言,若是是Flutter 開發者,須要先學習Dart 語言。

mixin Developer {
    bool isIOS = false;
    bool isAndroid = false;
    bool isFlutter = false;
    
    // 須要學習的基礎語言
    void needLearnBaseProgram () {
      if (isIOS) {
        print('Need Learn C Firstly');
      } else if (isAndroid) {
        print('Need Learn Java Firstly');
      } else if (isFlutter) {
        print('Need Learn Dart Firstly');
      } else {
        print('May be need Learn Other Language');
      }
    }
    
  }

class FlutterDeveloper with Developer {
	String name;
	FlutterDeveloper(String name) {
		isFlutter = true;
		this.name = name;
	}
}
  
複製代碼

使用的相關代碼:

FlutterDeveloper flutterDeveloper = FlutterDeveloper('FlutterEnginerName');
    flutterDeveloper.needLearnBaseProgram();
    
    // 輸出結果: flutter: Need Learn Dart Firstly
複製代碼

注意事項: 當在if else 場景下使用 bool 類型變量的時候,須要注意bool變量是否賦值過了,不然會有相似以下的異常信息。

flutter: The following assertion was thrown while handling a gesture:
flutter: Failed assertion: boolean expression must not be null
複製代碼

4. abstract

使用 abstract 修飾的類 記爲抽象類。抽象類用於定義接口 及部分實現。

筆者舉了以下例子:

建立了People 類,而且聲明瞭 String skinColor();的抽象方法,建立並實現了 void ability() 方法;

abstract class People {
  String skinColor();
  void ability() {
    print('All can Communicate');
  }

}

class YellowPeople extends People {
  @override
  String skinColor() {
    String color = 'Yellow';
    print(color);
    return color;
  }
}

class BlackPeople extends People {
  @override
    skinColor() {
      String color = 'black';
      print(color);
      return color;
    }
}

class WhitePeople extends People {
@override
  skinColor() {
    String color = 'White';
    print(color);
    return color;
  }
}
複製代碼

下邊是使用示例,及相應的輸出結果。

YellowPeople yellowPeople = YellowPeople();
yellowPeople.ability();
yellowPeople.skinColor();

WhitePeople whitePeople = WhitePeople();
whitePeople.ability();
whitePeople.skinColor();

BlackPeople blackPeople = BlackPeople();
blackPeople.ability();
blackPeople.skinColor();
    
// 輸出結果:
flutter: All can Communicate
flutter: Yellow
flutter: All can Communicate
flutter: White
flutter: All can Communicate
flutter: black

複製代碼
  • 抽象類不能建立實例。
  • 抽象方法爲沒有方法體的方法。只有抽象類中能夠寫抽象方法,其餘普通類不能夠。
    • 例:若是BlackPeople的skinColor 沒有方法體即沒有實現,則會報錯以下:'skinColor' must have a method body because 'BlackPeople' isn't abstract. Try making 'BlackPeople' abstract, or adding a body to 'skinColor'.
  • 繼承了抽象類的子類必須實現抽象方法
    • 以WhitePeople 爲例,若是不實現skinColor 方法會報出以下錯誤:
      • Missing concrete implementation of People.skinColor.
      • Try implementing the missing method, or make the class abstract.

5. override

"5.1 override 運算符"及override toString

這裏筆者對override 運算符添加了引號。至於緣由,等你們看完了下邊的內容以後,便會了解筆者的用意。下文提到的override和重寫是一個意思。

先看下運算符重寫的示例代碼:

Vector 類,重寫了+ 運算符和減運算符,以達到Vector能夠直接進行加減的目的。筆者還重寫了Vector類的toString 方法,便於查看Vector的x、y值。

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

  Vector operator +(Vector v) {
    return Vector(x + v.x, y + v.y);
  }

  Vector operator -(Vector v) {
    return Vector(x - v.x, y - v.y);
  }
  
  @override
  String toString() {
    return 'runtimeType:' + this.runtimeType.toString() + ',x:' + x.toString() +',y:' + y.toString();
  }
  
}

複製代碼

使用Vector的+、-運算符,及重寫toString後,使用Vector的示例代碼及輸出結果以下:

Vector v1 = Vector(1, 1);
    Vector v2 = Vector(2, 2);
    Vector v3 = v1 + v2;
    Vector v0 = v2 - v1;
    print(v0);
    print(v3);

// 輸出結果: 
flutter: runtimeType:Vector,x:1,y:1
flutter: runtimeType:Vector,x:3,y:3

複製代碼

重寫toString的效果是:可控制print的對象的內容及格式。 這一點便於非調試環境下查看一些具體錯誤信息。

上文筆者提到了重寫運算符是加引號的緣由以下:在筆者看來,運算符的重寫有點跑題了。重寫toString纔算是重寫。重寫的toString的返回值、方法名和參數和父類Object都同樣。如你們有不一樣理解,歡迎討論。

參考學習網址


小編微信:可加並拉入《QiShare技術交流羣》。

關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)

推薦文章:
Dart基礎(一)
Dart基礎(二)
Dart基礎(三)
iOS 短信驗證碼倒計時按鈕
iOS 環境變量配置
iOS 中處理定時任務的經常使用方法
算法小專欄:貪心算法
iOS 快速實現分頁界面的搭建
iOS 中的界面旋轉
奇舞週刊

相關文章
相關標籤/搜索