我有一个需要传递元素类型的类,因此以后我可以检查另一个对象是否具有该类型或该类型的子类,并将其添加到内部集合中。
我有一个initialize:
方法,可以从我班上的new:
控制器中调用:
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)
之类的东西。这是练习的一部分,因此请原谅示例:)
答案 0 :(得分:5)
正如我在对您的问题的评论中提到的那样,问题在于5 asNumber
是5
,它是SmallInteger
的实例,而不是Number
的实例。因此,当您使用initialize:
5
上课时,在ivar type
中得到的内容是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
的{{1}}。
现在让我补充一句话。 isKindOf: Number
的常用语义不同于您使用的语义。 new:
的参数通常是new:
,并且此类和整数表示新实例的所需大小。例如,当您想要具有Integer
个条目的Array new: 3
时说Array
,等等。3
预期不会收到其他类型的参数来构造宾语。我并不是说这是禁止的,只是那不是通常的命名约定。在您的情况下,我建议使用一种创建实例的方法,例如
new:
您的代码看起来像
MyClass class >> on: aClass
^self new initialize: aClass