Answers:
吉拉德·布拉查(Gilad Bracha)谈了become:
一段话
Smalltalk最独特和强大的功能之一也是Smalltalk社区之外鲜为人知的功能之一。这是一种称为成为的小方法。
变成的是:交换了接收者的身份和论据。也就是说,之后
a成为:b
在调用点之前,对由a表示的对象的所有引用均指代由b表示的对象,反之亦然。
花一点时间将其内部化;您可能会误以为是琐碎的事情。这并不是交换两个变量,而是从一个对象变成另一个对象。我不知道具有此功能的任何其他语言。这是巨大力量和危险的特征。
考虑扩展语言以支持持久对象的任务。假设您要从磁盘加载对象,但又不想传递其引用的所有对象(否则,这只是普通的对象反序列化)。因此,您可以加载对象本身,而不是加载直接引用,而是将它们替换为外壳对象。
外壳代表辅助存储上的实际数据。该数据被延迟加载。当您实际上需要在外壳上调用方法时,它的didNotUnderstand:方法从磁盘加载相应的数据对象(但同样,不是可传递的)。
然后,它变成了:将对外壳的所有引用替换为对新加载的对象的引用,然后重试该调用。
某些持久性引擎几十年来一直在做这种事情-但它们通常依赖于对表示形式的低级访问。成为:允许您在源代码级别执行此操作。
现在,用Java去做。甚至使用另一种动态语言。您将认识到,您可以通过这种方式来做期货的一般形式,因此变得懒惰。所有人都没有特权访问实现的工作方式。例如,当您将实例变量添加到类中时,它对于架构演变也很有用。您可以根据需要“重塑”所有实例。
当然,您不应该随便使用成为:这是有代价的,在许多实现中这可能是禁止的。在早期的Smalltalks中,变得便宜:因为所有对象都是通过对象表间接引用的。在没有对象表的情况下,变为:以类似于垃圾收集器的方式遍历堆。您拥有的内存越多,变得越昂贵。
具有对象表会占用存储空间并减慢访问速度;但确实可以为您带来很大的灵活性。硬件支持可以减轻性能损失。好处是,如果您愿意通过对象表预先支付间接开销,那么许多难题将变得很棘手。请记住:计算机科学中的每个问题都可以通过额外级别的间接解决。例如,亚历克斯·沃思(Alex Warth)的作品非常有趣,属于这一类。
成为:具有多种变体-一种方式成为:将对象A的标识更改为另一个对象B的标识,以使对A的引用现在指向B;对B的引用保持不变。变得很有用:批量-改变数组中所有对象的标识(单向或双向)。成为一个小组:例如,从根本上讲神奇的魔术对实现系统的反射更新非常有用。您可以一次更改一整套类及其实例。
您甚至可以构思出类型为safe的:。两种方式成为:仅当A的类型与B的类型相同时才是类型安全的,而一种方式变为:仅要求新对象是旧对象的子类型。
现在可能是时候重新考虑拥有一个对象表是否真的是一件好事了。
实际上,您所获得的是某种形式的延迟加载,这相当于元编程。正如Bracha指出的那样,这可能非常有用,但同时也会带来严重的性能影响,因此非常危险。
Hardware support could ease the performance penalty.
在我所听到的所有地方中,Smalltalk社区是最著名的。我们为什么要在实现理想的编程范例上“花钱”硬件改进,而又可能导致性能提高,功耗降低或功能增强。
它不是很多使用。在我打开的Pharo 5图片中,有9个#become发件人:其中7个正在单元测试中。它在代码生成的编译器和Fuel序列化库中用于通过代理内容替换代理。
become
的是对我的理智的影响,而不是对程序性能的影响……