如何在 Dart 中使用不定長度參數?
不定長度參數在 JavaScript 這類動態語言很常見,但 Dart 是靜態語言,不支援這個特性。本文介紹三種實現方式。
一共有三種解法可達成,一種是用 List
代替,一種是如 Rust 一樣使用 Builder Pattern,而最後一種是用 Class 模擬 Function。個人偏好 List
,再來是 Builder Pattern
。
使用列表(List)來代替可變參數(var-args)是最方便的。
class SuperHeroesHandler {
void handleSuperHeroes(List<String> superHeroes) {
for (final superHero in superHeroes) {
print("There's no stopping ${superHero}");
}
}
}
void main() {
final superHeroesHandler = SuperHeroesHandler();
superHeroesHandler.handleSuperHeroes(['UberMan', 'Exceptional Woman', 'The Hunk']);
}
在這個範例中,我們定義了一個 SuperHeroesHandler
類,其中包含一個 handleSuperHeroes 方法
。這個方法接受一個字串列表作為參數,該列表包含所有超級英雄的名字。在 main
函數中,我們創建了 SuperHeroesHandler
的一個物件,並調用了 handleSuperHeroes 方法,傳遞了一個包含三個超級英雄名字的列表。
而若遇到複雜一點的狀況,Builder Pattern 就比 List
適合 。這方式允許進行不定長度的參數設置。通過在每個設置方法(如 name
和 age
)結束時返回 Builder 對象本身實現的。這種方法稱為「流暢接口」(fluent interface)或「方法鏈」(method chaining),它允許連續調用多個方法,而不需要每次都從新的行或變數開始。
class Builder {
name(String name);
age(int age);
call();
}
void main() {
Builder()
..name("mark")
..age(16)
.call()
}
例如,在 Builder()
之後,可以連續調用 .name("mark")
和 .age(16)
,每次調用都返回 Builder 對象,從而允許下一個方法的調用。最後,.call()
方法則用於完成構建過程並獲取最終的對象。
最後一個方式是用 Emulating Function
模擬,作法如下:
typedef OnCall = dynamic Function(List arguments);
class VarargsFunction {
VarargsFunction(this._onCall);
final OnCall _onCall;
noSuchMethod(Invocation invocation) {
if (!invocation.isMethod || invocation.namedArguments.isNotEmpty)
super.noSuchMethod(invocation);
final arguments = invocation.positionalArguments;
return _onCall(arguments);
}
}
main() {
final superHeroes = VarargsFunction((arguments) {
for (final superHero in arguments) {
print("There's no stopping ${superHero}");
}
}) as dynamic;
superHeroes('UberMan', 'Exceptional Woman', 'The Hunk');
}
這段源碼展示了如何在 Dart 中使用 noSuchMethod
方法來實現一個接受不定長度參數的函數。通過定義一個 VarargsFunction
類來實現的,該類可以接受任意數量的參數並對它們進行操作。玩法跟在 Python 的 __call__
玩法類似。
總而言之,當遇到類似需求時,請直接以 List 傳遞,複雜一點用 Builder Pattern 。Emulating Function
則知道可以這麼做就好。有點複雜,降低維護性,暫時想不到哪裡能用到。