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 鐵人陣,祝團隊挑戰成功。