`
RednaxelaFX
  • 浏览: 3009297 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

关于对象与闭包的关系的一个有趣小故事

阅读更多
在一个邮件列表里看到一段很有趣的小故事:
RE: What's so cool about Scheme?
Anton van Straaten 写道
  The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said "Master, I have heard that objects are a very good thing - is this true?"  Qc Na looked pityingly at his student and replied, "Foolish pupil - objects are merely a poor man's closures."

  Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire "Lambda: The Ultimate..." series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system.  He learned much, and looked forward to informing his master of his progress.

  On his next walk with Qc Na, Anton attempted to impress his master by saying "Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures." Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object." At that moment, Anton became enlightened.

哈哈,Anton用十分风趣的口吻把对象与闭包之争的“宗教性”描写了出来。无论从哪个角度出发都能说得通,所以实在没什么争执的必要……
分享到:
评论
2 楼 RednaxelaFX 2008-09-21  
我不理解你不理解的是什么……闭包的定义很好理解撒。要点有俩:
1、一个含有自由变量的函数;
2、这些自由变量所在的环境。
外部环境持有内部函数所使用的自由变量,对内部函数形成“闭包”,就这样。
简单但不严格的说,一个函数的“自由变量”就是既不是参数也不是局部变量的变量。

一个纯粹(无副作用)的函数如果不含有自由变量,那么每次用相同的参数调用后的得到的结果肯定是一样的。但如果一个函数含有自由变量,那么调用返回的结果不但依赖于参数的值,还依赖于自由变量的值。因此一个含有自由变量的函数要正确执行,必须保证其所依赖的外围环境的存在。

基于类的面向对象程序语言中有一种情况,就是方法是用的自由变量是来自其所在的类的实例的。像这样:
class Foo {
    private int x;
    int AddWith( int y ) { return x + y; }
}

这样的AddWith()有一个参数y和一个自由变量x,其返回的值既依赖于参数的值也依赖于自由变量的值。为了让AddWith()正确工作,它必须依附于Foo的一个实例,不然就得不到x的值了(称为:“变量i未与值相绑定”)。很好理解对吧。不过面向对象的语言里一般不把类称为闭包,没为什么,就是种习惯。
当然严格来说方法所捕获的自由变量不是i,而是this;x是通过this来访问到的,完整写出应该是this.x。

如果这个“外围环境”来自一个外围函数,并且内部函数可以作为返回值返回,那么外围函数的局部环境就不能在调用结束时就撤销。也就是说不能在栈上分配空间。
function AddWith(x) {
    return function(y) {
        return x + y
    }
}

这样的内部函数有一个参数y和一个自由变量x。x在外围函数AddWith()里是一个参数,也就是一个“已绑定了值的变量”(bound variable)。AddWith()的局部作用域中含有内部函数所使用的自由变量,对内部函数形成闭包。为了让返回出去的内部函数能正常工作,这个内部函数必须依附于一个能提供x的值的环境,也就是AddWith()提供的闭包。这样我们就能够:
var addFive = AddWith(5)
var seven = addFive(2) // 2+5=7


全局变量是一种特殊的自由变量。
1 楼 lwwin 2008-09-21  
closure的定义每次都被FX搞糊涂=v=+

不知道FX大自己的理解是怎样的呢~很微妙似的……

相关推荐

Global site tag (gtag.js) - Google Analytics