1. 程式人生 > >帶你Dart帶你Diao之類(一)

帶你Dart帶你Diao之類(一)

在前面的系列文章(文章末尾會有傳送門哦~~)都是些比較簡單的基礎概念,之後就要開始介紹一些注重理解和手動實踐的Dart知識了。這篇的內容主要是Dart中的類的構造方法。

Dart是一種面向物件的語言,具有類和基於mixin的繼承。每個物件都是一個類的例項,所有的類都是Object的子類。

核心內容如下

  • 普通構造方法
  • 常量構造方法
  • 初始化列表
  • 工廠構造方法

類的成員

和java語言類似,使用點號(.)引用例項變數或方法

var p = Point(2, 2);
// Set the value of the instance variable y.
p.y = 3;

但它還可以這麼寫

// If p is non-null, set its y value to 4.
p?.y = 4;

這是為避免最左運算元為空時出現異常,使用 ?.代替 .

構造方法

  • 普通構造方法

如果不宣告構造方法,則為您提供預設構造方法。預設構造方法沒有引數,並在超類中呼叫無引數建構函式。

如果有多個構造方法,構造方法的寫法和Java不太一樣。即使構造方法的引數不同,這些構造方法的命名也不能重複

那如果有多個構造方法,我們可以通過ClassName.identifier作為它的構造方法,比如下面的Point.fromJson

class Point{
  var  x;
  var  y;

  Point(var x,var y){
    this.x=x;
    this.y=y;
  }

  Point.fromJson(Map<String, int> map) {
        x=map['x'];
        y=map['y'];
    }    
}

呼叫構造方法

var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});

當然我們這裡的new關鍵字是可以省略的

在Dart2中new關鍵字為可選關鍵字

  • 常量構造方法

 
class ImmutablePoint {
   final num x, y;
   const ImmutablePoint(this.x,this.y);//常量構造方法
}

常量構造方法需要新增關鍵字const,並且是沒有身體的,直接在末尾加;即可

var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);
assert(identical(a, b));
print(a==b);    //true
print(b);       //Instance of 'ImmutablePoint'

構造兩個相同的編譯時常量會生成一個單一的、規範的例項

在常量上下文中,可以在建構函式或文字之前省略const。例如,它建立了一個const的 map集合

//這裡用來很多const
const pointAndLine = const {
  'point': const [const ImmutablePoint(0, 0)],
  'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};

//可以省略除第一個外的其他const
const pointAndLine = {
  'point': [ImmutablePoint(0, 0)],
  'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};
  • 初始化列表

上面的Point類我們可以這麼寫

Point.fromJson(Map<String, int> map):
    x=map['x'],
    y=map['y']{
    print('In Point.fromJson(): ($x, $y)');
}

呼叫超類構造方法之外,還可以在建構函式主體執行之前初始化例項變數,初始值設定項用逗號分開。

可以通過在初始化列表中使用assert來驗證輸入

Point.withAssert(this.x, this.y) : assert(x >= 0) {
  print('In Point.withAssert(): ($x, $y)');
}

這樣寫有什麼好處呢?

初始化列表在設定final欄位時很方便

我們在構造方法的body裡設定final變數是不能編譯通過,但通過這種方式就是ok的

import 'dart:math';

class Point {
  final num x;
  final num y;
  final num distanceFromOrigin;

  Point(x, y)
      : x = x,
        y = y,
        distanceFromOrigin = sqrt(x * x + y * y);
}

main() {
  var p = new Point(2, 3);
  print(p.distanceFromOrigin);
}

///執行結果
3.605551275463989
  • 工廠構造方法

工廠構造方法可以從快取返回例項,也可以返回子型別的例項
在實現構造方法時使用factory關鍵字,工廠構造方法並不總是建立類的新例項。

class Logger {
  final String name;
  bool mute = false;

   //用於快取已經例項化的物件
  static final Map<String, Logger> _cache =
      <String, Logger>{};

  factory Logger(String name) {
    if (_cache.containsKey(name)) { //如果map快取裡存在直接返回例項
      return _cache[name];
    } else {   //如果map快取裡不存在,則返回新的例項
      final logger =  Logger._test(String name):this.name=name;;
      _cache[name] = logger;
      return logger;
    }
  }

//???
  Logger._internal(this.name);
  

  void log(String msg) {
    if (!mute) print(msg);
  }
}

上面程式碼還是比較好理解的,不知道在我標記問號的那句程式碼你有沒有懵逼?反正我看的時候是感覺有點奇怪的。

其實仔細一研究,它其實等價於這樣的寫法

Logger._internal(String name):this.name=name;

Dart相關係列的傳送門