如何让一个类使用两个不同的名称公开相同的方法?
例如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 [ "???" ]
]
答案 0 :(得分:5)
在Smalltalk中,您通常实现#printOn:
并从继承的版本中获取#asString
,
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
之间的一致性。此外,它将为您提供开始熟悉Streams
的机会,width asString
在Smalltalk中起着至关重要的作用。
请注意,在我的实现中,我使用了heigh asString
和String
。您的代码尝试将Number
与'Element with width ', width, ' and height ', height.
串联(两次):
String
不起作用,因为您只能将#,
的实例与#asString
连接起来。
但是,在大多数方言中,可以避免使用#print:
而不是#nextPutAll:
发送Element >> printOn: aStream
aStream
nextPutAll: 'Element with width ';
print: width;
nextPutAll: ' and height ';
print: height
,例如:
nextPutAll: self class name;
nextPutAll: ' with width ';
较不冗长,因此是首选。
最后一件事。我建议使用此命令更改上面的第一行:
Element
而不是对类名进行硬编码。如果将来您将#printOn:
子类化,这将被证明是有用的,因为您将无需调整#asDescription
及其任何派生词(例如#asDescription
)。
最后的想法:我将选择器#description
重命名为as
。介词#asString
旨在将一个对象转换为另一个不同类的对象(这就是#asString
可以的原因)。但这似乎并非如此。
使用#printOn:
来实现#printOn:
是有原因的,而不是相反的: generality 。尽管工作量(代码复杂度)相同,但是Stream
显然是赢家,因为它将与任何字符FileStream
一起使用。特别是,它将在不进行任何修改的情况下工作
SocketStream
的实例)Transcript
的实例)#printOn:
换句话说,通过实现#asString
可以免费(继承)获得Transcript
,并且可以同时在文件和套接字上转储对象表示形式。 Stream
特别有趣,因为它支持-webkit-overflow-scrolling:touch
overflow: auto
协议进行写入,因此可以在将任何字节发送到外部设备之前用于测试目的。
在Smalltalk中,目标是使对象的行为既简单又一般,不仅简单!
答案 1 :(得分:2)
如潜伏者在评论中所写,请在asDescription中发送asString消息。
asDescription
^ self asString
通常这样做是为了暴露类的其他接口/协议,以实现兼容性或作为内置适配器。如果您创建了不需要在其他任何地方使用的新内容,请考虑为每个操作仅保留一个名称。
编辑:如果您确实是在重新导出语义之后,并且不希望上述委托中包含其他消息发送,则可能有一种方法可以将asString的CompiledMethod再次放入类的方法字典中用另一个名字。但是我既不确定这是否行得通,也不知道GNU Smalltalk中的协议如何操作方法字典。看一下Behavior
类的文档。另外,我不认为这是对Smalltalk进行编程,而是对系统进行修改。