Seb*_* N. 10 oop smalltalk visualworks squeak pharo
在Smalltalk中,如果您没有明确地返回任何内容,则传递的消息将评估为接收者(或消息上下文中的"self").
例如,给定此方法:
MyClass >> myMethod
Transcript show: 'hello'; cr.
Run Code Online (Sandbox Code Playgroud)
评估(doint"print-it")这个:
| myInstance |
myInstance := MyClass new.
myInstance myMethod.
Run Code Online (Sandbox Code Playgroud)
如果对最后一次调用执行<print-it>,则结果将是实例本身.
Ber*_*erg 12
尚未说明一个非常简单的原因:在虚拟机中,返回self比返回任何其他对象更简单,更有效.
Smalltalk字节代码实现堆栈机器.这意味着通过将参数推送到堆栈来传递参数,而不是将它们放入寄存器中.除了方法签名中列出的参数之外,还始终传递隐藏参数,该参数是消息的接收者.因此,即使对于一元方法(没有参数的方法),接收器被推入堆栈,然后执行该方法,并且堆栈上的接收器值是方法知道"自我"的方式.如果没有给出明确的return语句,则返回"self",VM可以将"self"oop留在堆栈上,这样可以节省至少一个内存存储操作.因此,从效率和简单的角度来看,返回"自我"是最优雅的事情.
Smalltalk-80的蓝皮书(语言及其实现)没有说明为什么它默认返回接收器.
但是,第27页("返回值"部分)中的引用可能对您有所帮助:
"即使没有信息需要传回给发送者,接收者也总是返回消息表达式的值.返回值表示对消息的响应已完成.(...)"
请记住,Smalltalk方法是通过消息发送激活的,因此消息有一个完整的往返(可能以MessageNotUnderstood异常结束).消息发送的概念至关重要.
根据信息的意图,有什么好的实践模式可以归还,但这是其他故事的主题.
出于多种原因,方法默认返回 self 。
让我再解释一下#4。对象初始化的一种常见模式是为类定义一个新方法,如下所示:
new
^super new initialize
Run Code Online (Sandbox Code Playgroud)
这种模式取决于初始化返回的自我。然而,在initialize方法的末尾添加^self是不正常的。这是不必要的,因为该方法无论如何都会返回 self 。
最后,默认情况下,返回 self 只是一个自然的选择,因为您必须返回一些东西。
我不是smalltalk的创造者,但它似乎是最好的事情.
例如,如果您将执行:
var := myInstance myMethod.
Run Code Online (Sandbox Code Playgroud)
然后问题是:你想var成为什么?一种选择是nil.但它有点令人困惑,因为您正在使用已定义的对象,nil实际上是一个未定义的对象.因此,您可以在分配时对待它myInstance,var并在此过程中调用myMethod.这也可以作为速记来对待
var := myInstance myMethod; yourself.
Run Code Online (Sandbox Code Playgroud)
如果您从内部看,那么从对象本身可用的所有数据中,最合适的事情也可能是self.nil可以再次返回,但我之前已经告诉了我的意见.
在Smalltalk中,没有返回任何内容的void方法,并且没有类型检查.所以方法只需返回一些东西.就像对象说:
默认情况下,我可以返回任何方法调用,因为我总是了解自己,如果您希望我返回其他内容,您可以重新定义此行为.
我个人认为返回nil可能也很好,Objective-C应用程序nil经常使用东西,但Smalltalk是这样制作的,我认为这是一个非常好的解决方案.