iT邦幫忙

2021 iThome 鐵人賽

DAY 5
0
Modern Web

Flutter web 的奇妙冒險系列 第 5

Day05 | Dart基本介紹 - class、factory

類別

前面說到 Dart 是一個支援OOP的程式語言(附註*),而不同於JS的Prototype-based,Dart 則是 Class-based,所以在OOP上會比較像是Java之類的語言。

在 Dart 中 class的宣告很簡單

class Person {
  final String name;
  final int age;
  final String email;
  late final String position; // 請先無視這個late 之後會提到null safety時會再說明
  Person(this.position,
      {required this.name, required this.age, required this.email});
  Person.developer(
      {required this.name, required this.age, required this.email}) {
    this.position = 'developer';
  }

  void hello() {
    print('hi 我是 $name 我的職業是 $position');
  }
}

我們可以直接宣告一些變數來表示這個class的fields以及一些function來表示這個class的method,這些統稱是class members,那這個與class同名的function Person 是什麼呢?

這個就是所謂的建構子(constructor),在OOP中 class 可以想像成一個模板,而所謂的物件就是按照模板產生出來的東西,這個過程又稱為實體化(instantiation)

而在OOP裡負責這件事情就是 constructor ,而constructor當然可以不只有一個,我們可以宣告多個constructor來因應各種需求,像是可能許多人的 position 都是 developer那我們可以宣告一個 constructor 叫做 Person.developer 來減少我們只用原本的constructor還要一直多傳 position 的煩躁感。

真正在程式中run起來會像是這樣子:

void main() {
  
  final todd = Person('developer',name:'todd',age:25,email:'123@gamil.com');
  final larry = Person.developer(age:25,name:'larry',email:'456@gamil.com');

  print(todd.email);
  print(todd.name);
  print(todd.job);
  print(todd.age);
  todd.hello();
  larry.hello();

}

https://ithelp.ithome.com.tw/upload/images/20210917/20112906IYv4jBvUiu.png

也許有人已經注意到為什麼在
Person(this.position,{required this.name, required this.age, required this.email});

有些參數是放在 {}裡有些參數是放在前面,他們差別在哪裡?直接放在前面的參數是required positional parameters 而放到大括號中的是 Named parameters。

從這個例子先不考慮有default value(optional parameters )的情況下我們就能看得出 positional parameters它就跟一般function一樣我們要必須傳值並且要依照參數順序,而Named parameters就是我們以key:value的形式傳入參數而且 {}裡的順序可以隨意但必須在positional parameters後傳入。

Factory

在 Dart class constructor 中有提供一個語法糖 factory ,我們先來看看它的大概會長怎麼樣,稍微將上面的 Person Class 修改一下後:

class Person {
  final String name;
  final int age;
  final String email;
  late final String position;
  Person(
      {required this.name,
      required this.age,
      required this.email,
      required this.position});
  Person.developer(
      {required this.name, required this.age, required this.email}) {
    this.position = 'developer';
  }
  factory Person.todd(String name) {
    return Person(
        name: name, age: 25, email: '123@gamil.com', position: 'developer');
  }

  void hello() {
    print('hi 我是 $name 我的職業是 $position');
  }
}

最直觀的差異就是 factory constructor 會回傳一個 instance ,而不是像一般的 constructor 只要傳入值或者對this操作來設定值且不用另外撰寫return相關的語法。也因為是直接回傳 instance 所以就無法對 this 操作

那實際上 factory 有什麼用途?

大致上有三種

  1. 我希望不是每一次呼叫constructor都一定會建立一個新的instance,而是根據情況來決定要不要創建新的instance
  2. 我希望這個class 只能有一個instance(沒錯就是單例模式,singleton pattern )
  3. 不是要回傳這個class而是要回傳這個它的子class

在這裡我就先不詳細實作每種用法,如果有興趣可以查閱文章最後的參考資料。


下篇文章會繼續講解在Dart 中 class 的其他語法,預期會有 private、getter、setter 等等物件導向相關的語法及操作。

附註*:為什麼我不直接稱Dart為「物件導向程式語言」而是用「支援物件導向的程式語言」,主要是因為Dart不只支援一種 Programming paradigm,而我平常在工作中是比較常使用FP的概念在開發,所以面對這種支援多種 paradigm 的語言時我就不太喜歡稱為它是某個特定 paradigm 的語言。

參考資料:https://stackoverflow.com/questions/53886304/understanding-factory-constructor-code-example-dart


上一篇
Day04 | Dart基本介紹 - 變數宣告與基本型別
下一篇
Day 06 | Dart基本介紹 - private & static
系列文
Flutter web 的奇妙冒險30

尚未有邦友留言

立即登入留言