13

背景

在 Smalltalk 中,如果您没有明确返回任何内容,则传递的消息将评估为接收者(或消息上下文中的“自我”)。

例如,给定这个方法:

MyClass >> myMethod
  Transcript show: 'hello'; cr.

评估(点“打印”)这个:

| myInstance |
myInstance := MyClass new.
myInstance myMethod.

如果 <print-it> 执行到最后一次调用,则结果将是实例本身。

问题

  • 为什么这样设计?
  • 它背后的想法是什么?
  • 哲学背景是什么?
  • 它有什么实际好处?是为了方便方法链接吗?
4

5 回答 5

17

一个非常简单的原因还没有说明:在虚拟机中,返回 self 比返回任何其他对象更简单、更有效。

Smalltalk 字节码实现了堆栈机。这意味着通过将参数推入堆栈而不是将它们放入寄存器来传递参数。除了方法签名中列出的参数之外,始终传递一个隐藏参数,它是消息的接收者。因此,即使对于一元方法(那些没有参数的方法),接收者也被压入堆栈,然后执行该方法,堆栈上的接收者值是该方法如何知道“自我”的方式。如果没有给出明确的 return 语句,则通过返回“self”,VM 可以将“self” oop 留在堆栈上,这至少节省了一次内存存储操作。所以从效率和简单的角度来看,回归“自我”是最优雅的事情。

于 2012-12-30T15:40:08.913 回答
8

Smalltalk-80 的蓝皮书(语言及其实现)没有说明为什么它默认返回接收者。

但是,第 27 页(“返回值”部分)中的引用可能对您有所帮助:

“即使不需要将任何信息传回发送者,接收者也总是会返回消息表达式的值。返回值表示对消息的响应已完成。(...)”

请记住,在 Smalltalk 中,方法是通过消息发送来激活的,因此消息有一个完整的往返行程(可能以 MessageNotUnderstood 异常结束)。消息发送的概念是最重要的。

根据消息的意图,有一些关于返回什么的良好实践模式,但这是其他故事的主题。

于 2012-12-27T02:11:49.847 回答
6

方法默认返回 self 有几个原因。

  1. Smalltalk 方法必须返回一些东西
  2. self 是最容易返回的对象
  3. self 是最快返回的对象
  4. 返回 self 允许几种设计模式自然地工作

让我再解释一下#4。对象初始化的一种常见模式是为类定义一个方法,如下所示:

new
   ^super new initialize

这种模式取决于初始化返回的自我。但是,在初始化方法的末尾添加^self是不正常的。这是不必要的,因为该方法无论如何都会返回 self 。

最后,返回 self 只是默认情况下的自然选择,因为您必须返回一些东西。

于 2013-01-05T01:45:12.630 回答
6

我不是闲聊的创造者,但这似乎是最好的选择。

例如,如果您将执行:

var := myInstance myMethod.

那么问题来了:你想var成为什么样的人?一种选择是nil. 但这有点令人困惑,因为您正在使用已定义的对象并且nil实际上是未定义的对象。因此,您可以将其视为分配myInstance给它,var并在此过程中调用 myMethod。这也可能被视为

 var := myInstance myMethod; yourself.

如果您从内部看,那么从对象本身可用的所有数据来看,最合适的可能也是self. 再一次,nil可以退回,但我之前已经说过我的意见。

在 Smalltalk 中,没有不返回任何内容的void方法,也没有类型检查。所以一个方法只需要返回一些东西。就像对象说:

默认情况下,我可以为任何方法调用返回自己,因为我始终了解自己,并且您可以重新定义此行为,以防您希望我返回其他内容。

我个人认为返回nil可能也不错,Objective-C应用程序nil经常使用这些东西,但是 Smalltalk 是这样制作的,我认为这是一个很好的解决方案。

于 2012-12-27T00:55:02.337 回答
0

来自 Java 的您在处理未定义的返回值时知道 NullPointExceptions。此外,您的代码必须在这里和那里对 null 进行条件检查。

因此,我很高兴为 Smalltalk 中的每个方法调用或消息发送找到一个返回值。如果您决定让每个方法都返回一些值,那么您将要问您的默认值可能是什么。对象本身(self)是一种非常自然的方式来用作默认值。或者反过来问:什么是更好的回报值?

于 2012-12-27T15:12:50.837 回答