就像Java,C#等。我如何在Smalltalk中定义类似enum Direction { input, output }
的内容?
答案 0 :(得分:4)
最简单的方法是让类方法返回符号或其他基本对象(如整数)。
所以你可以按如下方式编写你的例子:
Direction class>>input
^ #input
Direction class>>output
^ #output
用法:
Direction input
主要缺点是:
^ self name + '::input'
)更好的方法是创建自己的枚举对象并返回它的实例。
这样的对象应该:
=
和hash
,因此您可以按值对它们进行比较,并使用枚举作为哈希集合中的键(字典)printOn:
方法来简化调试它可能看起来像这样
Object subclass: #DirectionEnum
slots: { #value }
classVariables: { }
category: 'DirectionEnum'
"enum accessors"
DirectionEnum class>>input
^ self new value: #input
DirectionEnum class>>output
^ self new value: #output
"getter/setters"
DirectionEnum>>value
^ value
DirectionEnum>>value: aValue
value := aValue
"comparing"
DirectionEnum>>= anEnum
^ self class = anEnum class and: [ self value = anEnum value ]
DirectionEnum>>hash
^ self class hash bitXor: self value hash
"printing"
DirectionEnum>>printOn: aStream
super printOn: aStream.
aStream << '(' << self value asString << ')'
用法仍然相同
Direction input.
DirectionEnum output asString. "'a DirectionEnum(output)'"
解决了琐碎方法中提到的问题。
显然这是更多的工作,但结果更好。如果你有很多枚举,那么将基本行为移动到新的超类Enum
是有意义的,然后DirectionEnum
只需要包含类方法。
答案 1 :(得分:3)
与枚举类型最接近的Smalltalk功能是SharedPool
(a.k.a。PoolDictionary
)。因此,如果您将某些枚举从Java转移到Smalltalk,则可能需要使用SharedPool
。以下是如何操作:
对于您类型中的每个枚举,您将在池中定义一个关联,其中key
为类型名称,value
为类型值。
在某些方言中PoolDictionaries
是字典,在Pharo中它们是SharedPool
的子类。因此,在Pharo中,您将所有类型名称声明为类变量。然后在初始化方法(类侧)中将值与键关联。
例如,您可以使用类变量SharedPool
等定义名为ColorConstants
的{{1}}的子类,如下所示:
'Red', 'Green', 'Blue', 'Black', 'White'
要将名称与值相关联,请在以下行添加类侧初始化方法:
SharedPool
subclass: #ColorConstants
instanceVariableNames: ''
classVariableNames: 'Red Green Blue Black White'
poolDictionaries: ''
package: 'MyPackage'
评估ColorConstants class >> initialize
Red := Color r: 1 g: 0 b: 0.
Green := Color r: 0 g: 1 b: 0.
Blue := Color r: 0 g: 0 b: 1.
Black := Color r: 0 g: 0 b: 0.
White := Color r: 1 g: 1 b: 1.
"and so on..."
后,您就可以在班级中使用该池
ColorConstants initialize
在Object
subclass: #MyClass
instanceVariableNames: 'blah'
classVariableNames: ''
poolDictionaries: 'ColorConstants'
package: 'MyPackage'
(及其子类)中,您可以按名称引用颜色:
MyClass
答案 2 :(得分:2)
由于Smalltalk是动态类型的,因此无论如何都不能将变量的值限制为对象的子集,因此枚举成员和全局常量之间没有区别,除了通过枚举名称的命名空间。
编辑:有关如何定义枚举常量的选项,请参阅Peter的答案。请允许我提一下,如果满足您的需求,您也可以直接使用符号。 direction := #input. direction := #output
答案 3 :(得分:2)
对于简单的情况,只需使用彼得建议的符号 - 您也可以将可能的值存储在IdentityDictionary
中。
如果你的意思是Java中可用的更强大的枚举(它们可能不仅仅是一种命名常量;它们可以有行为,复杂的属性等),那么我就拿它比Peter更进一步,只为每个枚举类型创建一个子类。即使您正在谈论大量的枚举(您的用例似乎只需要两个),也不要害怕拥有许多子类,其中只有一个或两个方法用于区分他们彼此相处,大部分工作都是在共同的超类中完成的。