iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0
Software Development

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

Day 21:像呼叫函式一樣的呼叫類別吧。(Callable class)

物件導向的基本原則之一:單一職責原則,每一個類別裡它的職責應該只有一個,那麼在這樣的設計底下,很有可能類別只有一個函數。

例如:

class Logger{
	String message;
	Logger(this.message);

	void sendMessage(){
		print('Sending message: $message');
	}
}

呼叫的時候,就必須帶入函數的名稱。

void main(){
	var logger = Logger('This is sample log');
	logger.sendMessage();
}
//This is sample log

Callable Class

Dart 提供了一個特別的方法,如果類別裡面有一函數的名稱為 call ,那麼該函數則不需要名稱就可以呼叫。

class Logger{
	String message;
	Logger(this.message);

	void call(){
		print('Sending message: $message');
	}
}
void main(){
	var logger = Logger('This is sample log');
	logger();
}
//This is sample log

這樣一來,便可以把類別轉換成可以呼叫的樣子。(A class can be called like a function)

當然,我們也是可以用 call() 來呼叫

void main(){
	var logger = Logger('This is sample log');
	logger.call();
}
//This is sample log

這樣做有什麼好處呢?

有些函數的呼叫需要輸入不同的參數,根據不同的參數,我們可以得到不同的結果。

如上面的範例,我們將參數轉成類別的屬性,當呼叫類別的 call() 時,就可以直接取用。

舉一個 Flutter 的範例:

有一個類別,專門用來儲存圖片的位置,在該類別裡面包含了一個 call() 函數,我們可以直接呼叫將圖片的位置轉換成圖片。

class DisplayImage{
	String imagePath;
	String(this.imagePath);

	Image call(){
		return Image.asset(path, fit: BoxFit.cover);
	}
}
  • 只要這樣呼叫,就可以將圖片位置轉為 Image Widget。
DisplayImage('image path')();
  • 看起來就像是呼叫一個函數,且因為 DisplayImage 的命名,使用者直覺就會認為這樣就可以產生出一個 Image。

假設沒有使用 call() 函數:

class DisplayImage{
	String imagePath;
	String(this.imagePath);

	Image toImageWidget(){
		return Image.asset(path, fit: BoxFit.cover);
	}
}
DisplayImage('image path').toImageWidget();
  • 最後還需要呼叫 toImageWidget() 來將圖片路徑轉成 Image Widget,看起來比較冗長一點。

使用 Callable Class 需注意的地方

  • 一個類別只有一個 call() 方法,但是除了 call() 之外,還是可以使用其他的方法名稱,只不過就沒有辦法不使用函數名稱來呼叫。

  • call() 函數也可以帶參數。

class Logger{
	void call(String message){
		print('Sending message: $message');
	}
}
  • BTW,也可以將上例改為頂層函數。

小記

Callable class 讓我們可以思考的是,類別中的哪一個函數可以被放在 call() 函數中。我認為 call() 函數放的是這個類別主要的工作。當呼叫者呼叫時,就可以清楚知道這個類別的主要工作是什麼。不需要多餘的函數名稱來誤導呼叫者。

那麼,如果類別裡只有一個函數,該用頂層函數 (top-level function) 還是 Callable class 呢?如果函數的工作需要跟類別的屬性有關係,用 Callable class 比較適合;反之,可以使用頂層函數。不過這個答案沒有絕對,完全取決於程式設計方向。


上一篇
Day20:泛型 (Generic)
下一篇
Dart 22:將函數定義成型別吧。 (Typedef)
系列文
Dart 語言 - 開啟 Flutter 的鑰匙30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言