Smalltalk 如何在变量中存储对象的类型?
我有一个需要传递元素类型的类,因此我可以稍后检查另一个对象是否具有该类型或是该类型的子类,并将其添加到内部集合 我有一个Smalltalk 如何在变量中存储对象的类型?,smalltalk,pharo,Smalltalk,Pharo,我有一个需要传递元素类型的类,因此我可以稍后检查另一个对象是否具有该类型或是该类型的子类,并将其添加到内部集合 我有一个initialize:方法,该方法从类的new:ctor调用: initialize: aType elements := OrderedCollection new. type := aType class. 现在我有了一个方法,它传递了一个值,应该检查类型是否兼容: add: anElement type isNil ifTrue: [ ele
initialize:
方法,该方法从类的new:
ctor调用:
initialize: aType
elements := OrderedCollection new.
type := aType class.
现在我有了一个方法,它传递了一个值,应该检查类型是否兼容:
add: anElement
type isNil ifTrue: [ elements add:anElement. ^self. ].
(anElement isMemberOf: type)
ifTrue: [elements add:anElement.]
ifFalse: [ ^ 'Not supported!' ].
如果要检查混凝土类型,则此选项有效:
|myClass|
myClass:= MyClass new: '123'.
cc add: '5.4'. "Works"
cc add: 123. "Fails correctly."
现在,为了检查它是否是派生类型,我修改了add:
方法:
add: anElement
type isNil ifTrue: [ elements add:anElement. ^self. ].
(anElement isKindOf: type)
ifTrue: [elements add:anElement.]
ifFalse: [ ^ 'Not supported!' ].
但是,这不起作用:
|myClass|
myClass:= MyClass new: 5 asNumber.
myClass add: 5.4. "Fails, although Float is a sub type of Number"
我怀疑我最初确定对象类型的方法(
aType class
)是错误的,但我找不到更好或更明确的方法来确定类型。基本上,我正在寻找类似C#中的typeOf(MyObject)
。这是练习的一部分,因此请原谅这个人为的例子:)正如我在对你的问题的评论中提到的,问题是5asnumber
是5
,它是SmallInteger
的一个实例,而不是Number
的一个实例。因此,当您初始化:
使用5
初始化您的类时,您在ivar类型中得到的是SmallInteger
。然后,当您add:5.4
时,检查变成5.4 isKindOf:SmallInteger
,这自然会失败
我认为问题源于您选择的初始化实例的方式。一种更简单的方法是使用类而不是实例显式地设置目标type
。关于
initialize: aClass
elements := OrderedCollection new.
type := aClass
然后,你的例子会是
|myClass|
myClass:= MyClass new initialize: Number.
myClass add: 5.4.
它将接受5.4
作为一个元素,因为它是一个Float
,而是一种数字
现在让我补充一点。new:
的常用语义与您使用的不同。new:
的参数通常是一个整数
,这样的和整数表示新实例的所需大小。例如,当您想要一个包含3
项的Array
时,您会说Array new:3
。不希望new:
接收用于构建对象的其他类型的参数。我不是说这是禁止的,只是这不是通常的命名惯例。在您的情况下,我建议创建实例的方法,例如
MyClass class >> on: aClass
^self new initialize: aClass
你的代码看起来像
| sequence |
sequence := MyClass on: Number.
sequence add: 5. "ok, 5 isKindOf: Number"
sequence add: 4.5. "ok, 5.4 isKindOf: Number"
sequence add: 'hello world' "fail, not a Number"
在上一个示例中,您定义了myClass
变量,然后执行cc add:5.4
cc
是另一个变量。如果您在操场中执行此操作,cc
将被初始化为零。您得到了什么错误?问题是5asnumber==5
是SmallInteger
而不是Number
。因此,5.4
不是它的子类型。@AndreiChis:谢谢你提供的信息,那是我的复制/粘贴错误。它们应该是相同的。也许还可以考虑使用一个谓词(通过一个块),比如MyClass-restrictedTo:[:x | x isInteger和:[x>0]
包含其他可能性MyClass-restrictedTo:[:x | x isMemberOf:Character]
或MyClass-restrictedTo:[:x | x isKindOf:Number]
。可能类似于MyCollection of:Number
而不是on:?