在dart中是否有更好的方法来映射成员函数?



Dart在可迭代对象上有一个方便的map函数,它接受一个lambda。所以我可以这样写:

// Stupid example class
class Foo {
int v;
int v2() { return v*v; }
}
List<int> mapFoos(List<Foo> foos) {
return foos.map( (Foo f) => f.v2() );
}

但是我觉得这有点笨拙。我习惯告诉map直接使用成员函数,类似于:

// does not compile
List<int> mapFoos(List<Foo> foos) {
return foos.map(Foo.v2);
}

但是编译失败,并报错:

The argument type '() → int' can't be assigned to the parameter type '(Foo) → int'

是否有办法以简洁的方式将成员函数转换为lambda,以便我们可以得到更接近第二个例子的东西。

我可以写

int applyV2(Foo f)  {
return f.v2();
}
List<int> mapFoos(List<Foo> foos) {
return foos.map(applyV2);
}

但是我需要为我想要映射的每个成员函数创建它,这并不比使用lambda函数好。

如果由于"遗留原因",我使用第1段有什么不同,如果这在最近的版本中有所改变,我也很想知道。

No.

没有比(f) => f.v2()更短的方法来创建一个接受Foo并调用其v2方法的函数。您可以省略参数上的Foo类型,因为它可以从上下文中推断出来(List<X>.map<R>需要R Function(X)作为参数)。

不能剥离Foo.v2,因为v2是一个接口方法,而不是静态方法。

详细说明为什么Dart不允许这样做,如果你只是想知道什么是有效的,你现在可以停止阅读:有些语言允许剥离实例方法,因此Foo.v2成为一个函数,它将this对象作为参数,在Dart中是一个int Function(Foo)类型的函数。达特不允许这样做。可能有很多不同的原因,但最重要的是因为它行不通。Dart类型是接口,所有类类型都可以由另一个类实现,而无需继承任何实现。如果你去掉Foo.v2,你可以用另一个实现Foo的类的实例来调用它,但是它不一定能找到Foo拥有的私有字段,而v2可能依赖于私有字段。

同样,撕扯在其this-参数中将是协变的。以SubFoo为例,它扩展了Foo并拥有自己的v2方法。如果您执行Foo foo = SubFoo(); var vtoo = foo.v2;,那么vtoo的静态类型将是int Function(Foo),但是SubFoo的实现必然具有运行时类型int Function(SubFoo),这是而不是静态类型的子类型。这意味着它是不可靠的。被删除的函数必须进行运行时类型检查,以确定其参数实际上是SubFoo,如果不是则抛出。(因此,该功能不适合Dart。)

最新更新