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

plo*_*man 29 dart

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

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

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

superHeroes('UberMan', 'Exceptional Woman', 'The Hunk');
Run Code Online (Sandbox Code Playgroud)

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

Ale*_*uin 22

你现在不能这样做.

我真的不知道varargs是否会回来 - 他们曾经在那里,但已被删除.

但是,可以使用模拟功能模拟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');
}
Run Code Online (Sandbox Code Playgroud)


Lad*_*cek 6

如果您确实希望语法简洁,只需声明一个带有 10 个可选位置参数的函数/方法即可。不太可能有人会用超过 10 个参数来调用它。

如果这听起来像黑客,那是因为它确实黑客。但我已经看到 Dart 团队也在做同样的事情:-)

例如

void someMethod(arg0, [arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9]) {
  final args = [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9];

  args.removeWhere((value) => value == null);

  /* do something the the args List */
  print(args);
}
Run Code Online (Sandbox Code Playgroud)


Son*_*low 6

只要您不太了解语法简洁,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]);
Run Code Online (Sandbox Code Playgroud)

注意:您可以使用命名参数做同样的事情,但您必须在内部处理事情,以防万一(该函数的用户;可能是您)决定不向该命名参数传递任何值。


我要感谢@Ladicek 间接地让我知道英语中存在像简洁这样的词 。

  • 这是我在打开此页面之前个人想到的。看到这里的所有答案后,我选择继续使用这个解决方案,因为另一个解决方案看起来像是一个黑客。我不喜欢每个函数的定义方式。是的,我不太喜欢语法简洁。 (2认同)

plo*_*man 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');
}
Run Code Online (Sandbox Code Playgroud)

这有很多问题,包括:

  • 在您调用的任何地方都会生成警告,superheroes()因为签名与您的参数不匹配.
  • 需要进行更多的手动检查以确保传递给超级英雄的参数列表确实是一个List<String>.
  • 需要检查成员名称,noSuchMethod()如果更改方法名称,则更有可能忘记更改"超级英雄"字符串.
  • 反射使代码路径更难追踪.

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


Dev*_*wal 5

这个版本:

  1. 适用于位置和关键字参数。
  2. 支持输入返回值。
  3. 适用于现代 Dart。
typedef VarArgsCallback = void Function(List<dynamic> args, Map<String, dynamic> kwargs);

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

  VarArgsFunction(this.callback);

  void 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);
        },
      ),
    );
  }
}

void 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}
}
Run Code Online (Sandbox Code Playgroud)

谢谢,亚历山大的回答