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:?