如何在GNU Smalltalk中添加具有2个不同名称的相同方法?

时间:2019-03-24 09:34:40

标签: smalltalk gnu-smalltalk

如何让一个类使用两个不同的名称公开相同的方法?

例如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 [ "???" ]
]

2 个答案:

答案 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 asStringString。您的代码尝试将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一起使用。特别是,它将在不进行任何修改的情况下工作

  1. 文件(SocketStream的实例)
  2. 套接字(Transcript的实例)
  3. #printOn:

换句话说,通过实现#asString可以免费(继承)获得Transcript,并且可以同时在文件和套接字上转储对象表示形式。 Stream特别有趣,因为它支持-webkit-overflow-scrolling:touch overflow: auto 协议进行写入,因此可以在将任何字节发送到外部设备之前用于测试目的。

记住!

在Smalltalk中,目标是使对象的行为既简单又一般不仅简单!

答案 1 :(得分:2)

如潜伏者在评论中所写,请在asDescription中发送asString消息。

asDescription
    ^ self asString

通常这样做是为了暴露类的其他接口/协议,以实现兼容性或作为内置适配器。如果您创建了不需要在其他任何地方使用的新内容,请考虑为每个操作仅保留一个名称。

编辑:如果您确实是在重新导出语义之后,并且不希望上述委托中包含其他消息发送,则可能有一种方法可以将asString的CompiledMethod再次放入类的方法字典中用另一个名字。但是我既不确定这是否行得通,也不知道GNU Smalltalk中的协议如何操作方法字典。看一下Behavior类的文档。另外,我不认为这是对Smalltalk进行编程,而是对系统进行修改。