不定長度參數在 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 適合 。這方式允許進行不定長度的參數設置。通過在每個設置方法(如 nameage)結束時返回 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 則知道可以這麼做就好。有點複雜,降低維護性,暫時想不到哪裡能用到。