如何在GNU Smalltalk中添加具有两个不同名称的相同方法?
如何让一个类用两个不同的名称公开同一个方法 例如,如何在GNU Smalltalk中添加具有两个不同名称的相同方法?,smalltalk,gnu-smalltalk,Smalltalk,Gnu Smalltalk,如何让一个类用两个不同的名称公开同一个方法 例如,asDescripton函数执行相同的操作/重新导出asString函数,而无需简单地复制粘贴代码 Object subclass: Element [ | width height | Element class >> new [ ^super new init. ] init [ width := 0. height := 0. ] asString [ ^ 'Elem
asDescripton
函数执行相同的操作/重新导出asString
函数,而无需简单地复制粘贴代码
Object subclass: Element [
| width height |
Element class >> new [
^super new init.
]
init [
width := 0.
height := 0.
]
asString [
^ 'Element with width ', width, ' and height ', height.
]
asDescription [ "???" ]
]
正如潜伏者在评论中所写的,在asDescription中发送asString消息
asDescription
^ self asString
这通常是为了从类中公开额外的接口/协议,以实现兼容性或作为内置适配器。如果你创建了一些不适合任何其他地方的新东西,考虑每个操作只停留一个名字。
编辑:如果您确实在重新导出语义,并且不希望在上面的委托中涉及额外的消息发送,那么可能有一种方法可以将asString的CompiledMethod第二次放在类的方法字典中的另一个名称下。但我既不确定这是否可行,也不知道GNU Smalltalk中的协议如何操作方法字典。查看
行为
类的文档。此外,我不认为这是SMALLAST编程,而是在修改StalTalk。Object >> asString
| stream |
stream := '' writeStream.
self printOn: stream.
^stream contents
在您的环境中,此方法的实际实现可能略有不同,但其思想保持不变
如上所述,实现#printOn:
而不是#asString
通常是一个好主意。在您的情况下,您可以将其实现为
Element >> printOn: aStream
aStream
nextPutAll: 'Element with width ';
nextPutAll: width asString;
nextPutAll: ' and height ';
nextPutAll: height asString
然后,正如JayK和luker所指出的
Element >> asDescription
^self asString
换句话说,您(通常)不想实现#asString
,而是#printOn:
。这种方法更好,因为它利用了继承,并确保了#printOn:
和#asString
之间的一致性,这通常是预期的。此外,它将使您有机会开始熟悉在Smalltalk中起核心作用的流
顺便注意一下,在我的实现中,我使用了width asString
和heigh asString
。您的代码尝试将字符串
与数字
连接(两次):
'Element with width ', width, ' and height ', height.
这不起作用,因为您只能将字符串的实例
与#,
连接起来
但是,在大多数方言中,您可以通过使用#print:
而不是#nextPutAll:
来避免发送#asString
,例如:
Element >> printOn: aStream
aStream
nextPutAll: 'Element with width ';
print: width;
nextPutAll: ' and height ';
print: height
这是一个少一点冗长,因此首选
最后一件事。我建议将上面的第一行改为:
nextPutAll: self class name;
nextPutAll: ' with width ';
而不是硬编码类名。如果将来您将元素子类化
,这将被证明是有用的,因为您将不需要调整#printOn:
及其任何衍生物(例如,#asDescription
)
最后一个想法:我将选择器#asDescription
重命名为#description
。介词as
用于将一个对象转换为另一个不同类的对象(这就是为什么#asString
可以的原因)。但这里的情况似乎不是这样
增编:为什么?
#asString
是根据#printOn:
实现的,这是有原因的,而不是相反:通用性。虽然付出的努力(代码复杂性)是相同的,#printOn:
显然是一个赢家,因为它可以处理任何字符流
。特别是,它将在没有任何修改的情况下工作
文件(文件流的实例)
套接字(SocketStream的实例)
成绩单
换句话说,通过实现#printOn:
可以免费获得#asString
(继承),同时还可以在文件和套接字上转储对象的表示。转录本
特别有趣,因为它支持写入的流
协议,因此可以在将任何字节发送到外部设备之前用于测试目的
记住强>
在Smalltalk中,目标是让对象的行为同时变得简单和一般,而不仅仅是简单您可以从asDescription
调用asString
选择器:asDescription[^asString]
。如果答案符合您的需要,请接受它-我认为CompiledMethod在st80及其子体中保留了指向方法选择器的指针。它主要用于反编译或检索源代码(在调试器中),但可能还有另一个我错过的用途。因此,我无法判断在methodDictionary中的两个不同选择器条目中共享相同的compiledMethod是否会产生副作用。值得一试……哦,有趣。实际上,我是以另一种方式实现的:我实现了printOn
,即asString
。来自哈斯凯尔的背景让人感觉更自然。@adius阅读附录,了解更多关于这方面的想法。