iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 30
0
Software Development

Dart 語言 - 開啟 Flutter 的鑰匙系列 第 30

Day 30:Metadata 以及完賽心得

Metadata 是用來替函數、參數加上註解,在 dart:core/annotations.dart 中提供了兩個 metadata。

@override

當類別用關鍵字 extend 繼承或是用 implement 實作其它類別。原類別內的有函數需要被覆寫。使用 IDE 產生未實作的函數,則會自動加上 @override metadata。
如下例:有一個抽象類別為 User,裡面包含了一個回傳 String 的 read 函數。若有另一個類別 AdminUserextend 繼承 User ,則 User 裡面的函數需要在 AdminUser 裡面被覆寫。
@override 可以提醒在 AdminUser 的 read() 函數是覆寫其他類別的。

abstract class User{
	String read();
}

class AdminUser extends User{

	@override
	String read(){
		
	}
	
	void write(String data){
		//do something
	}
}

@deprecated

開發函式庫時,隨著時間演進,原本因為某些用途開發的函數,可能在某一個版本之後,變得不在需要,但是你又不希望拔掉之後,其他人用新的函式庫會因為找不到該函數而導致錯誤。這時候可以加上 @deprecated
當函數加上了 @deprecated 之後,使用該函數的人依然可以正確使用,不過在 IDE 的介面上,就會看到該函數被用刪除線標記。此時,使用該函數的使用者,應該就必須要找到替代函數,以免某個版本之後該函數真的被拔掉而發生錯誤。

例如,假設原本的 Login 類別呼叫 login()時需代入 String username 以及 String password

class Login {
	void login(String username, String password){}
}

後來的版本覺得直接代入 String usernameString password 不太好,所以改帶入一個 LoginInfo info ,並且在原本的函數上方加上 @deprecated ,呼叫此函數的人就會注意到該函數已被棄用,所以就會尋找替代方案。

class Login {
	@deprecated
	void login(String username, String password){}

	void login(LoginInfo info){}
}
void main(){

	var login = Login();
	login.~~login("user", "123");~~
}

meta 函式庫

除了使用 Dart 原生 dart:core/annotations.dart 提供的 metadata,我們還可以使用 meta 函式庫提供的 meta。

package 位置:https://pub.dev/packages/meta

@immutable

將類別加上 @immutable 後,該類別裡的屬性就不得修改,意指所有屬性都必須加上 final 修飾。

  • 假設有一個訂單系統的 Model 如下:
class Order {
	int serialNo;
	List<Food> foods;
	Order(this.serialNo, this.foods);

	@override
	  String toString() {
	    return 'Order{serialNo: $serialNo, foods: $foods}';
	  }
	}

class Food{
  String name;
  int price;

  Food(this.name, this.price);

	@override
	  String toString() {
	    return 'Food{name: $name, price: $price}';
	  }
}
void main(){
	final food1 = Food('Hamburger', 100);
  final food2 = Food('Coke', 10);
  var order = Order(1, [food1, food2]);
  print(order);

  order.serialNo = 2;
  print(order);
}
//Order{serialNo: 1, foods: [Food{name: Hamburger, price: 100}, Food{name: Coke, price: 10}]}

//Order{serialNo: 2, foods: [Food{name: Hamburger, price: 100}, Food{name: Coke, price: 10}]}
  • 可以發現 order 物件在建立之後,還可以被修改。

將 Order 類別加上 @immutable

@immutable
class Order {
	final int serialNo;
  final	List<Food> foods;
	Order(this.serialNo, this.foods);

	@override
	  String toString() {
	    return 'Order{serialNo: $serialNo, foods: $foods}';
	  }
	}

class Food{
  String name;
  int price;

  Food(this.name, this.price);

	@override
	  String toString() {
	    return 'Food{name: $name, price: $price}';
	  }
}
void main(){
	final food1 = Food('Hamburger', 100);
  final food2 = Food('Coke', 10);
  var order = Order(1, [food1, food2]);
  print(order);

  order.serialNo = 2; //Compiliation-error
  print(order);
}
  • 類別加上 @immutable 後,IDE 就會溫柔地提醒你,該類別為不可修改的,需要將屬性加上 final

https://ithelp.ithome.com.tw/upload/images/20200930/20129264oHZjoXrvUh.png

@required

類別中,如果有命名式的參數,由於命名是的參數是可選的,所以有可能會發生少傳的情況,在一定需要的參數上加上 @required ,使用該類別且少傳參數時,IDE 也會溫柔地提醒你。

class Book {
	String isbn;
	String name;
	
	Book({@required this.isbn, @required this.name});
}

https://ithelp.ithome.com.tw/upload/images/20200930/20129264nI7rrP5VKi.png

小結

透過 metadata 的註解,可以讓我們在使用類別、函數上更有規範,避免不必要的失誤。

使用別人開發的函式庫,就像是在跟他交談,加上 metadata 可以幫助我們更清楚函式庫的意圖。


附錄:完賽心得

首先是很開心能夠完成這三十天的挑戰,為了要把文章寫好,所以把該篇主題好好的看了一遍,現在的我真的比三十天前的我強了一些。

回想一開始是因為參加了 Kotlin 練功場的聚會,且在社群裡面有人打算參賽,我也動搖參加的念頭,不過由於最近 Flutter 比較熟,所以選擇了與 Flutter 相關的主題。

看了很多 iT邦的文章,我發現大部分提到 Dart 的朋友,都是因為為了介紹 Flutter 才先介紹 Dart 。並沒有一個系列是有關於 Dart 的。所以我才會決定本次的主題是 Dart。

我的參考資料大部分都是來自於 Dart 的官方網站,如果你對於 Dart 也想深入了解,建議從官網下手,或是跟我一起來討論。

最後最後,我要感謝跟我一起奮鬥的小偉哥:菜雞們,讓我們一起征服JS及React吧,有你跟我一起努力,我更有動力把文章寫完,讓我們一起變強吧。

接者要謝謝 舒安:如何用 Ktor / Kotlin 開發 Chatbot (Chatbot小萌新攻略),在每一篇文章都有工商我的 Medium 文章。

最後要感謝的是 Kotlin 鐵人陣,祝團隊挑戰成功。

參考資料:

language-tour

effective-dart


上一篇
Dart 29:Dart 也有 Mockito!
系列文
Dart 語言 - 開啟 Flutter 的鑰匙30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言