我有一个需要传递元素类型的类,因此以后可以检查另一个对象是否具有该类型或该类型的子类,并将其添加到内部集合中。
我有一个initialize:从new:类的ctor 调用的方法:
initialize: aType
elements := OrderedCollection new.
type := aType class.
Run Code Online (Sandbox Code Playgroud)
现在,我有一个传递值的方法,应该检查类型是否兼容:
add: anElement
type isNil ifTrue: [ elements add:anElement. ^self. ].
(anElement isMemberOf: type)
ifTrue: [elements add:anElement.]
ifFalse: [ ^ 'Not supported!' ].
Run Code Online (Sandbox Code Playgroud)
如果我要检查具体类型,这可以工作:
|myClass|
myClass:= MyClass new: '123'.
cc add: '5.4'. "Works"
cc add: 123. "Fails correctly."
Run Code Online (Sandbox Code Playgroud)
现在,要检查它是否是派生类型,我修改了add:方法:
add: anElement
type isNil ifTrue: [ elements add:anElement. ^self. ].
(anElement isKindOf: type)
ifTrue: [elements add:anElement.]
ifFalse: [ ^ 'Not supported!' ].
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用:
|myClass|
myClass:= MyClass new: 5 asNumber.
myClass add: 5.4. "Fails, although Float is a sub type of Number"
Run Code Online (Sandbox Code Playgroud)
我怀疑确定对象(aType class)类型的最初方法是错误的,但是我找不到更好或更明确的确定类型的方法。基本上,我正在寻找类似typeOf(MyObject)C#的东西。这是练习的一部分,因此请原谅示例:)
正如我在你的问题的评论中提到,问题是,5 asNumber就是5这是一个实例SmallInteger,而不是一个实例Number。因此,当您initialize:将类与5ivar中的内容一起使用时,它type是SmallInteger。然后,当您时add: 5.4,检查变为5.4 isKindOf: SmallInteger,自然会失败。
我认为问题出在您选择初始化实例的方式上。一种更简单的方法是type使用类而不是实例来显式设置目标。一些东西
initialize: aClass
elements := OrderedCollection new.
type := aClass
Run Code Online (Sandbox Code Playgroud)
然后,您的示例将类似于
|myClass|
myClass:= MyClass new initialize: Number.
myClass add: 5.4.
Run Code Online (Sandbox Code Playgroud)
这将接受5.4作为一个元素,因为它是一个Float,这isKindOf: Number。
现在让我补充一句话。的常用语义new:不同于您使用的语义。的参数new:通常是Integerand,并且integer表示新实例的期望大小。例如,您说什么Array new: 3时候想要Array带3条目等。不希望为new:构造对象而接收其他类型的参数。我并不是说这是禁止的,只是那不是通常的命名约定。在您的情况下,我建议一种实例创建方法,例如
MyClass class >> on: aClass
^self new initialize: aClass
Run Code Online (Sandbox Code Playgroud)
你的代码看起来像
| 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"
Run Code Online (Sandbox Code Playgroud)