如何将对象的类型存储在变量中?

Len*_*art 4 smalltalk pharo

我有一个需要传递元素类型的类,因此以后可以检查另一个对象是否具有该类型或该类型的子类,并将其添加到内部集合中。

我有一个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#的东西。这是练习的一部分,因此请原谅示例:)

Lea*_*lia 5

正如我在你的问题的评论中提到,问题是,5 asNumber就是5这是一个实例SmallInteger,而不是一个实例Number。因此,当您initialize:将类与5ivar中的内容一起使用时,它typeSmallInteger。然后,当您时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时候想要Array3条目等。不希望为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)