我使用下面的内容来查看 dart 如何调用传入其他方法的方法,以查看传入方法将/可以在什么上下文下调用。
void main() {
var one = new IDable(1);
var two = new IDable(2);
print('one ${caller(one.getMyId)}'); //one 1
print('two ${caller(two.getMyId)}'); //two 2
print('one ${callerJustForThree(one.getMyId)}'); //NoSuchMethod Exception
}
class IDable{
int id;
IDable(this.id);
int getMyId(){
return id;
}
}
caller(fn){
return fn();
}
callerJustForThree(fn){
var three = new IDable(3);
three.fn();
}
Run Code Online (Sandbox Code Playgroud)
那么 manager 如何在没有上下文的情况下caller调用其参数ie ,以及为什么无法调用为其定义了该函数的对象传递的参数?fnone.fn()callerJustForThreefn
在 Dart 中,声明为类的一部分的实例方法与其他函数(如闭包和静态函数)之间存在差异。
实例方法是唯一可以访问this. 从概念上讲,它们是类描述的一部分,而不是对象。也就是说,当您执行方法调用时,o.foo()Dart 首先提取o. 然后它在类描述中搜索foo(如果需要,递归地遍历超类)。最后它应用找到的方法并将this其设置为o。
除了能够调用对象 ( o.foo()) 上的方法之外,还可以获得绑定闭包:(o.foo没有调用的括号)。然而,这一点至关重要,这种形式只是 的语法糖(<args>) => o.foo(<args>)。也就是说,这只是创建了一个新的闭包来捕获o并对它的调用重定向到实例方法。
整个设置有几个重要的后果:
您可以撕掉实例方法并获得绑定闭包。的结果o.foo自动绑定到o。不需要自己绑定它(但也没有办法将它绑定到不同的实例)。在你的例子中,这是可行one.getMyId的。您实际上得到了以下闭包:() => one.getMyId()相反。
无法向对象添加或删除方法。您需要更改类描述,而这是(故意)不支持的。
var f = o.foo;意味着你总是得到一个新的结束。这意味着您不能使用此绑定闭包作为哈希表中的键。例如,register(o.foo)后跟unregister(o.foo)很可能不起作用,因为每个 o.foo 都会不同。通过尝试,您可以轻松看到这一点print(o.foo == o.foo)。
您无法将方法从一个对象转移到另一个对象。无论您尝试访问实例方法,它们都将始终受到绑定。
看看你的例子:
print('one ${caller(one.getMyId)}'); //one 1
print('two ${caller(two.getMyId)}'); //two 2
print('one ${callerJustForThree(one.getMyId)}'); //NoSuchMethod Exception
Run Code Online (Sandbox Code Playgroud)
这些行相当于:
print('one ${caller(() => one.getMyId())}');
print('two ${caller(() => two.getMyId())}');
print('one ${callerJustForThree(() => one.getMyId())}';
Run Code Online (Sandbox Code Playgroud)
里面callerJustForThree:
callerJustForThree(fn){
var three = new IDable(3);
three.fn();
}
Run Code Online (Sandbox Code Playgroud)
给定的参数fn被完全忽略。当在最后一行执行时, Dart 会找到(即)three.fn()的类描述,然后在其中进行搜索。由于它找不到,它将调用后备。该参数被忽略。threeIDablefnnoSuchMethodfn
如果您想根据某个参数调用实例成员,您可以重写最后一个示例,如下所示:
main() {
...
callerJustForThree((o) => o.getMyId());
}
callerJustForThree(invokeIDableMember){
var three = new IDable(3);
invokeIDableMember(three);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2337 次 |
| 最近记录: |