如何在Smalltalk中以惯用方式定义枚举类型?含Java、C#风格示例
嘿,这个问题问到点子上了!Smalltalk不像Java或C#那样有原生的enum关键字,但社区里有几种非常成熟的惯用方式来实现类似的枚举效果,我给你分情况说明:
1. 实现类似
Direction { input, output }的强类型枚举 这是最接近Java/C#枚举的方案,核心是创建一个类,通过类侧方法暴露固定的实例,同时限制外部随意创建新实例:
# 首先创建Direction类 Object subclass: #Direction instanceVariableNames: 'displayName' classVariableNames: 'Input Output' poolDictionaries: '' category: 'MyApp-Enums' --- # 实例侧方法(用来存储枚举的属性) Direction>>initialize: aDisplayName displayName := aDisplayName Direction>>displayName ^ displayName --- # 类侧方法(管理枚举实例) Direction class>>initialize "类初始化时创建所有枚举实例" Input := self new initialize: 'Input'. Output := self new initialize: 'Output'. Direction class>>input ^ Input Direction class>>output ^ Output Direction class>>new "禁止外部直接创建新实例,保证枚举的唯一性" self error: '不能直接创建Direction实例,请使用input或output方法获取'
使用的时候就和Java/C#一样方便:
| myDirection | myDirection := Direction input. myDirection displayName. "返回 'Input'"
这种方式的好处是类型安全——如果你不小心传了一个不是Direction的对象,编译器会及时报错;而且你还可以给枚举添加自定义方法(比如判断是否是输入方向的isInput方法),扩展性很强。
2. 轻量方案:用Symbol快速实现
如果你的场景不需要强类型检查,只是需要一组固定的标识,直接用Smalltalk的Symbol(比如#input、#output)是最简单的方式:
| direction | direction := #input. "判断逻辑" direction = #input ifTrue: [ "处理输入逻辑" ]. direction = #output ifTrue: [ "处理输出逻辑" ].
这种方式的优点是零成本实现,但缺点也很明显:没有类型约束,如果你不小心写错成#inpt,编译器不会提示错误,只能在运行时发现问题。
3. 利用方言自带的枚举工具(以Pharo为例)
如果你用的是Pharo这类现代Smalltalk方言,它自带了Enumeration基类,可以帮你快速创建枚举:
Enumeration subclass: #Direction instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'MyApp-Enums' Direction class>>initialize self addEnumeration: #input. self addEnumeration: #output.
使用时同样可以通过Direction input获取枚举值,而且Enumeration基类还自带了很多实用方法,比如Direction allEnumerations可以获取所有枚举值,#input isEnumeration判断是否是枚举实例等,非常方便。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

