如何让一个类使用2个不同的名称公开相同的方法?
例如。 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 [ "???" ]
]
最佳答案
在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
与String
连接(两次):'Element with width ', width, ' and height ', height.
这将不起作用,因为您只能将
#,
的实例与#asString
并置。但是,在大多数方言中,可以避免使用
#print:
而不是#nextPutAll:
发送Element
,例如: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:
是有原因的:通用性。尽管工作量(代码复杂度)相同,但是Stream
显然是赢家,因为它可以与任何字符FileStream
一起使用。特别是,它将在不进行任何修改的情况下工作文件(
SocketStream
的实例)套接字(
Transcript
的实例)#printOn:
换句话说,通过实现
#asString
,可以免费(继承)获得Transcript
,并且可以同时将对象表示形式转储到文件和套接字上。 Stream
尤其有趣,因为它支持协议进行写入,因此可以在将任何字节发送到外部设备之前用于测试目的。记得!
在Smalltalk中,目标是使对象的行为既简单又通用,而不仅仅是简单!
关于smalltalk - 如何在GNU Smalltalk中添加具有2个不同名称的相同方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55322402/