在Dart中创建具有可变数量的参数或参数的函数

时间:2012-12-05 20:16:50

标签: dart

我正在寻找一种在Dart中使用可变数量的参数或参数创建函数的方法。我知道我可以创建一个数组参数,但我宁愿不这样做,因为我正在开发一个语法简洁很重要的库。

例如,在纯JavaScript中,我们可以做这样的事情(借鉴here):

function superHeroes() {
  for (var i = 0; i < arguments.length; i++) {
    console.log("There's no stopping " + arguments[i]);
  }
}

superHeroes('UberMan', 'Exceptional Woman', 'The Hunk');

然而,在dart中,该代码将无法运行。有没有办法在飞镖中做同样的事情?如果没有,这是路线图上的内容吗?

6 个答案:

答案 0 :(得分:19)

你现在不能这样做。

我真的不知道 varargs 是否会回来 - 他们曾在那里见过have been removed

但是可以使用Emulating functions模拟 varargs 。请参阅以下代码段。

typedef dynamic OnCall(List);

class VarargsFunction extends Function {
  OnCall _onCall;

  VarargsFunction(this._onCall);

  call() => _onCall([]);

  noSuchMethod(Invocation invocation) {
    final arguments = invocation.positionalArguments;
    return _onCall(arguments);
  }
}

main() {
  final superHeroes = new VarargsFunction((arguments) {
    for (final superHero in arguments) {
      print("There's no stopping ${superHero}");
    }
  });
  superHeroes('UberMan', 'Exceptional Woman', 'The Hunk');
}

答案 1 :(得分:5)

我在Alexandre Ardhuin的回答中玩了一下,发现我们可以调整一些东西,使其在当前版本的Dart中发挥作用:

class VarArgsClass {
  noSuchMethod(InvocationMirror invocation) {
    if (invocation.memberName == 'superheroes') {
      this.superheroes(invocation.positionalArguments);
    }
  }

  void superheroes(List<String> heroNames) {
    for (final superHero in heroNames) {
      print("There's no stopping ${superHero}!");
    }
  }
}

main() {
  new VarArgsClass().superheroes('UberMan', 'Exceptional Woman', 'The Hunk');
}

这有很多问题,包括:

  • 只要您拨打superheroes(),就会生成警告,因为签名与您的参数不符。
  • 需要进行更多的手动检查,以确保传递给超级英雄的参数列表真的是List<String>
  • 需要检查noSuchMethod()中的成员名称,如果更改方法名称,则更有可能忘记更改“超级英雄”字符串。
  • 反射使代码路径更难追踪。

但如果你对所有这些问题都很好,那么这就完成了工作。

答案 2 :(得分:3)

如果你真的想要语法简洁,只需声明一个函数/方法,并说明10个可选的位置参数即可。不太可能有人会用超过10个参数来调用它。

如果它听起来像是黑客,那是因为 是黑客攻击。但是我看到Dart团队做了同样的事情: - )

答案 3 :(得分:3)

只要您不太习惯语法简洁,Dart就会间接支持var-args。

void testFunction([List<dynamic> args=[]])
{
  for(dynamic arg:args)
  {
    // Handle each arg...
  }
}

testFunction([0, 1, 2, 3, 4, 5, 6]);
testFunction();
testFunction([0, 1, 2]);

注意:您可以使用命名参数执行相同的操作,但必须在内部进行处理,以防万一(该功能的用户;可能是您)决定不会将任何值传递给该命名参数。


我要感谢@Ladicek间接让我知道英语中存在诸如简洁之类的词。

答案 4 :(得分:2)

对于您编写的示例,我认为您最好使用列表。对不起!

我正在看dartbug.com,但我没有看到这方面的功能请求。你绝对欢迎创建一个!

答案 5 :(得分:0)

此版本:

  1. 同时使用位置和关键字参数。
  2. 支持键入返回值。
  3. 与现代Dart配合使用。
typedef T VarArgsCallback<T>(List<dynamic> args, Map<String, dynamic> kwargs);

class VarArgsFunction<T> {
  final VarArgsCallback<T> callback;
  static var _offset = 'Symbol("'.length;

  VarArgsFunction(this.callback);

  T call() => callback([], {});

  @override
  dynamic noSuchMethod(Invocation inv) {
    return callback(
      inv.positionalArguments,
      inv.namedArguments.map(
        (_k, v) {
          var k = _k.toString();
          return MapEntry(k.substring(_offset, k.length - 2), v);
        },
      ),
    );
  }
}

main() {
    dynamic myFunc = VarArgsFunction((args, kwargs) {
      print('Got args: $args, kwargs: $kwargs');
    });
    myFunc(1, 2, x: true, y: false); // Got args: [1, 2], kwargs: {x: true, y: false}
}

谢谢亚历山大(Alexandre)的answer