【发布时间】:2019-05-03 15:26:33
【问题描述】:
我有一个需要传递元素类型的类,因此我可以稍后检查另一个对象是否具有该类型或者是该类型的子类并将其添加到内部集合中。
我有一个 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# 中寻找类似 @987654330@ 的东西。这是练习的一部分,所以请原谅这个人为的例子:)
【问题讨论】:
-
在最后一个示例中,您定义了
myClass变量,然后执行cc add: 5.4。cc是另一个变量。如果您在操场上执行此操作,cc将被初始化为零。你得到什么错误? -
问题在于
5 asNumber == 5是SmallInteger而不是Number。因此5.4不是它的子类型。 -
@AndreiChis:感谢您提供的信息,这是我的复制/粘贴错误。它们应该是相同的。
-
也许还可以考虑使用谓词(通过块),例如
MyClass restrictedTo: [:x | x isInteger and: [x > 0]]包含其他可能性MyClass restrictedTo: [:x | x isMemberOf: Character]或MyClass restrictedTo: [:x | x isKindOf: Number]。