Metadata 是用來替函數、參數加上註解,在 dart:core/annotations.dart 中提供了兩個 metadata。
@override當類別用關鍵字 extend 繼承或是用 implement 實作其它類別。原類別內的有函數需要被覆寫。使用 IDE 產生未實作的函數,則會自動加上 @override metadata。
如下例:有一個抽象類別為 User,裡面包含了一個回傳 String 的 read 函數。若有另一個類別 AdminUser 用 extend 繼承 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 username 、 String 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");~~
}
除了使用 Dart 原生 dart:core/annotations.dart 提供的 metadata,我們還可以使用 meta 函式庫提供的 meta。
package 位置:https://pub.dev/packages/meta
@immutable將類別加上 @immutable 後,該類別裡的屬性就不得修改,意指所有屬性都必須加上 final 修飾。
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}]}
@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 。
@required類別中,如果有命名式的參數,由於命名是的參數是可選的,所以有可能會發生少傳的情況,在一定需要的參數上加上 @required ,使用該類別且少傳參數時,IDE 也會溫柔地提醒你。
class Book {
	String isbn;
	String name;
	
	Book({@required this.isbn, @required this.name});
}

透過 metadata 的註解,可以讓我們在使用類別、函數上更有規範,避免不必要的失誤。
使用別人開發的函式庫,就像是在跟他交談,加上 metadata 可以幫助我們更清楚函式庫的意圖。
首先是很開心能夠完成這三十天的挑戰,為了要把文章寫好,所以把該篇主題好好的看了一遍,現在的我真的比三十天前的我強了一些。
回想一開始是因為參加了 Kotlin 練功場的聚會,且在社群裡面有人打算參賽,我也動搖參加的念頭,不過由於最近 Flutter 比較熟,所以選擇了與 Flutter 相關的主題。
看了很多 iT邦的文章,我發現大部分提到 Dart 的朋友,都是因為為了介紹 Flutter 才先介紹 Dart 。並沒有一個系列是有關於 Dart 的。所以我才會決定本次的主題是 Dart。
我的參考資料大部分都是來自於 Dart 的官方網站,如果你對於 Dart 也想深入了解,建議從官網下手,或是跟我一起來討論。
最後最後,我要感謝跟我一起奮鬥的小偉哥:菜雞們,讓我們一起征服JS及React吧,有你跟我一起努力,我更有動力把文章寫完,讓我們一起變強吧。
接者要謝謝 舒安:如何用 Ktor / Kotlin 開發 Chatbot (Chatbot小萌新攻略),在每一篇文章都有工商我的 Medium 文章。
最後要感謝的是 Kotlin 鐵人陣,祝團隊挑戰成功。