成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

從Flutter范兒的單例來看Dart的構造函數

開發 前端
在Dart中,變量和函數前面加上「_」就代表私有,但這個私有實際上的含義是「只能在當前文件中訪問」,所以,如果在當前文件中,你依然是可以訪問這個私有變量或者函數的。另外,由于Dart是單線程模型,所以也不存在線程安全的問題,不用做線程控制。

單例模式

單例模式應該是設計模式中使用的最廣泛的一種設計模式了,在Kotlin中,甚至為它單獨創建了一個語法糖——object類,來快速實現單例模式,而在Dart中,并沒有像Kotlin這樣的語法糖,所以,參考單例的一般實現,我們可以很容易的實現下面這樣一個單例。

class Singleton {
  static Singleton? _instance;

  // 私有的命名構造函數
  Singleton._private() {
    // TODO
  }

  static Singleton getInstance() {
    if (_instance == null) {
      _instance = Singleton._private();
    }
    return _instance!;
  }
}

上面的代碼與大部分編程語言的代碼都差不多,不外乎就是單例的幾個特點:

  • 私有構造函數
  • 靜態instance訪問

在Dart中,變量和函數前面加上「_」就代表私有,但這個私有實際上的含義是「只能在當前文件中訪問」,所以,如果在當前文件中,你依然是可以訪問這個私有變量或者函數的。另外,由于Dart是單線程模型,所以也不存在線程安全的問題,不用做線程控制。

上面的代碼,作為一個Dart初學者來說,是無可厚非的,但是對于老司機來說,明顯沒有Flutter范兒,所以,我們借助Dart的語法糖,來改造下上面的單例代碼。

class Singleton {
  static Singleton? _instance;

  // 私有的命名構造函數
  Singleton._private() {
    // TODO
  }

  static Singleton get instance => _instance ??= Singleton._private();
}

首先,通過「??=」來簡化空判斷,其次,通過get函數來獲取實例,將instance函數變成了instance變量。這樣一來,代碼簡化了不少,而且也更加簡單了。

不過,這依然不是最具Flutter范兒的單例寫法,在Dart中,它提供了一個factory關鍵字,與Kotlin中的object關鍵字,有異曲同工之妙,我們來看看官方推薦的單例寫法。

class Singleton {
  static final Singleton _singleton = Singleton._internal();

  factory Singleton() => _singleton;

  Singleton._internal() {
    // TODO
  }
}

?所謂的factory constructor,它的作用是「僅在第一次創建實例,后續都返回相同的實例」,這不就是天然的單例嗎,所以,借助factory constructor,我們可以很方便的寫出一個Flutter范兒的單例。

構造函數

構造函數是一個類在初始化時,主動調用的函數,在Dart中,有多種不同的構造函數,它們在不同的場景下使用,可以極大的簡化我們的代碼,同時也讓我們的代碼更加具有Flutter范兒。

默認構造函數

缺省構造函數不用自己創建,如果一個類沒有構造函數,那么它會自動添加一個,它什么都不做。

// Default Constructor
class Test {
  String name = 'xys';
  Test();
}

在構造函數中初始化變量

Dart提供了多種不同的方式在構造函數中未變量賦值,其中最簡單的,就是在構造時初始變量。

// Constructor with parameters
class Test {
  String name;
  Test(this.name);
}

其實Test(this.name)實際上就是Test(String name){this.name = name}的簡化寫法。

同時,構造函數也可以增加方法體,進行一些初始化邏輯。

// Constructor with the initial method
class Test {
  String name;
  Test(this.name) {
    // TODO
  }
}

?當你需要在構造函數初始化時給變量賦值時,可以通過initializer list來實現。

// Constructor with initializer
class Test {
  String name;
  
  Test(name) : name = handleSth(name);
  
  static String handleSth(String e) => e.toUpperCase();
}

initializer list可以初始化多個變量,它們之間可以使用「,」進行分隔,如果有super構造器,那么它一般放在最后。

如果你要override基類的變量,那么可以通過super關鍵字來覆寫。

// Constructor with super()
class Base {
  String id;
  Base(this.id);
}
class Test extends Base {
  String name;
  Test(this.name, String id) : super(id);
}

另外,構造函數中,還支持通過Asserts?來做一些檢查。

// Constructor with assertion
class Test {
  String name;
  Test(this.name) : assert(name.length > 3);
}

對于Dart的參數來說,通常我們設置的都是必選參數,就是類似我們上面的這些參數,而在Dart中,還可以設置可選參數。

class Test {
  String name;

  Test(this.name, [int sex = 0]);
}

Test('xys', 1);

或者你覺得可選參數在使用時的語義不太明確,那么你可以使用具名參數。

class Test {
  String name;

  Test(this.name, {int sex = 0});
}

Test('xys', sex: 1);

這樣在使用時,語義會更加明確。

私有構造函數

私有構造函數,除了我們前面提到的單例使用場景外,下面這個場景,也使用的很多。

class Utils {
  Utils._();
  static void log(String message) => print(message);
}

通過私有構造函數,我們可以避免使用者創建工具類的實例,而是讓使用者直接調用靜態函數。

具名構造函數

具名構造函數可以給當前的構造邏輯起一個別名,方便調用者通過語義來進行調用。

// Constructor with this()
class Test {
  String name;
  int sex;
  Test(this.name, this.sex);
  Test.boy(String name) : this(name, 1);
  Test.girl(String name) : this(name, 0);
}

const構造函數

const構造函數在Flutter中使用的非常多,因為一個const構造函數是不可變的,const構造函數在運行時會指向內存空間的同一個對象,從而提高代碼執行的效率,所以,在Flutter中,如果一個Widget是可以定義為const的,那就把它定義為const吧。

factory構造函數

factory constructor前面我們已經講解過了,它可以從另一個構造函數,或者是其它類,返回一個唯一的實例。最常用的場景就是單例的使用,我們來看下它的另一個使用場景,即從緩存中返回唯一實例。

class Test {
  final String name;

  static final _cache = <String, Test>{};

  Test._(this.name);

  factory Test(name) => _cache[name] ??= Test._(name);
}

factory構造函數與static method的區別

在大部分時間,這兩者都是非常類似的,甚至是可以混用的,但是它們之間,還是有一些區別的。

對于factory constructor來說,它不需要命名,也不用指定通用參數,這樣可以減少很多模板代碼,我們來看下面這個例子。

class ComplexClass<Value, Notifier extends ValueNotifier<Value>> {}

在這個例子中,它包含一個比較復雜的泛型,如果我們要創建一個靜態工廠,那么就需要這樣:

class ComplexClass<Value, Notifier extends ValueNotifier<Value>> {
  static ComplexClass<Value, Notifier> someFactory<ComplexClass<Value, Notifier extends ValueNotifier<Value>>() {
    // TODO: return a ComplexClass instance
  }
}

我們需要創建很復雜的參數類型,但是使用factory constructor,則可以避免這些模板代碼。

class ComplexClass<Value, Notifier extends ValueNotifier<Value>> {
  factory ComplexClass.someFactory() {
    // TODO: return a ComplexClass instance
  }
}


責任編輯:武曉燕 來源: 群英傳
相關推薦

2011-02-13 17:24:36

SAPSybase

2012-07-11 09:48:35

2015-09-08 15:37:08

2017-07-05 14:21:39

常青藤

2011-10-12 11:18:20

打印機評測

2009-07-21 12:35:00

Scala從構造器

2015-10-27 09:19:24

2025-02-06 13:23:09

C++函數參數

2016-10-17 14:51:44

自然語言數據科學語義分析

2021-09-07 10:44:35

異步單例模式

2024-03-13 13:44:06

DartFlutterSDK

2010-04-20 14:15:49

負載均衡產品

2016-09-19 10:01:08

NodeJSWeb

2017-04-17 08:44:43

構造函數線程安全

2018-02-08 16:48:36

匠心IBM數據存儲

2018-02-26 10:38:38

數據保護

2019-06-11 09:50:07

SparkBroadcast代碼

2022-02-06 22:30:36

前端設計模式

2023-11-13 16:49:51

C++單例
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久久一区二区三区 | 亚洲欧美中文日韩在线v日本 | 亚洲午夜精品一区二区三区 | 欧美video| 成人黄色在线 | 精品一区二区三区在线视频 | 免费特黄视频 | 99草免费视频 | 国产一区二区三区视频免费观看 | 午夜性色a√在线视频观看9 | 2019中文字幕视频 | 午夜看电影在线观看 | 欧美jizzhd精品欧美巨大免费 | 精品久久久久一区二区国产 | 999久久久久久久久6666 | 亚洲国产一区二区三区在线观看 | 综合久久一区 | 91精品国产91久久久久久最新 | 国产一区二区影院 | av免费观看网站 | 国产精品99| 亚洲精品高清视频在线观看 | 久一精品 | 国产精品久久久久久久久久久久 | 亚洲一区| 91www在线观看| 国产精品国产a级 | 国产亚洲高清视频 | 成人一区二区三区 | 毛片网在线观看 | 中文字幕在线观看视频网站 | 欧美成人精品一区 | 欧美日韩淫片 | 久久久久久久久久性 | 人人爽人人爽 | 一区二区三区回区在观看免费视频 | 成人av网页| 韩日精品在线观看 | 91在线看网站 | 国产一级网站 | 精品自拍视频在线观看 |