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

问题描述 投票:2回答:2

如何让一个类用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 gnu-smalltalk
2个回答
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之间的一致性,这通常是预期的。此外,它将让您有机会开始熟悉在Smalltalk中扮演核心角色的Streams

请注意,在我的实现中,我使用了width asStringheigh 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 ';

而不是硬编码类名。如果将来你继承qa​​zxswpoi,这将证明是有用的,因为你不需要调整Element及其任何衍生物(例如,#printOn:)。

最后的想法:我会将选择器#asDescription重命名为#asDescription。介词#description旨在将一个对象转换为另一个不同的类(这就是为什么as没问题)。但这似乎并非如此。

Addendum: Why?

#asString#asString来实现是有原因的,而不是相反:普遍性。尽管努力(代码复杂性)是相同的,但#printOn:显然是胜利者,因为它可以与任何角色#printOn:一起使用。特别是,它无需任何修改即可使用

  1. 文件(Stream的实例)
  2. 套接字(FileStream的实例)
  3. SocketStream

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

记得!

在Smalltalk中,目标是让对象的行为既简单又通用,而不仅仅是简单!


2
投票

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

Stream

通常这样做是为了从类中公开其他接口/协议,以实现兼容性或作为内置适配器。如果您创建了一些不必适合其他任何地方的新内容,请考虑为每个操作只添加一个名称。

编辑:如果你真的在重新导出语义之后并且不希望上面的委托中涉及额外的消息发送,那么可能有一种方法将asString的CompiledMethod第二次放在该类的方法字典中名称。但我不确定这是否有效,我也不知道GNU Smalltalk中的协议如何操作方法字典。看看asDescription ^ self asString 类的文档。另外,我不认为这是编程Smalltalk,而是修补系统。

© www.soinside.com 2019 - 2024. All rights reserved.