如何在smalltalk中为实例变量指定类

时间:2017-12-07 15:09:25

标签: smalltalk squeak

可能我还没有理解smalltalk的概念,但这是我的问题:

我正在创建一个类,我们称之为 Main-class ,它有一个实例变量 bar ,我想成为某个类 - 其他类,并在 Main-class 方法中使用此 Other-class '方法,如下所示:

    Object subclass: #Other-class
        instanceVariableNames: 'foo'
        classVariableNames: ''
        poolDictionaries: ''
        category: 'Custom-class'

setFoo: newFoo

    foo := newFoo.

Main-class

  Object subclass: #Main-class
        instanceVariableNames: 'bar'
        classVariableNames: ''
        poolDictionaries: ''
        category: 'Custom-class'

newBar: val

    bar := Bar new. 
    bar setFoo: val.

显然,我收到一条错误,即没有 setFoo 方法。 但是,如何指定我希望 bar 是特定类的变量,然后在其上使用该类的方法?

2 个答案:

答案 0 :(得分:4)

关于问题的标题:你没有。 Smalltalk是一种动态类型语言,这意味着变量的值在不同的时间点可以有不同的类型 - 不为变量声明类型。但对于人类,您可以在类注释中注意变量的实际类型(请参阅系统浏览器中实例端和类侧按钮旁边的?按钮)。

关于您的问题:您必须确保分配给实例变量bar的对象是合适的类型。在这种情况下,它必须理解消息setFoo:。在您的第二个代码段中,这意味着:

  1. 您应该使用另一个可以响应Bar的类,而不是setFoo:,例如Other-class(由于连字符,这是一个奇怪的名字,你不能轻易在你的方法中引用,改为使用CamelCase,填充变量,或
  2. 必须为课程setFoo:实施Bar

答案 1 :(得分:0)

respondsTo:方法可用于确定对象是否响应消息:

bar respondsTo: #setFoo
  ifTrue: [bar setFoo: val]
  ifFalse: [missiles launch]

如果您在bar不理解setFoo时想要发射导弹,请确定您想要发生的事情。也许你的程序会因错误而崩溃。这不像发射导弹那么极端,但仍然有点极端,很少你真正想要的,特别是如果其他人正在使用你的软件。

选项:只需使用正确类型的对象

ifFalse: [bar := ClassWithSetFoo new; setFoo: val]

选项:通过修改类

来扩展对象以执行所需操作
ifFalse: [ (bar class) addInstVarName: 'foo'.
           (bar class) compile: 'setFoo: newFoo [foo := newFoo]'.
           bar setFoo: val. ]

根据上下文,第二个选项可能是您想要做的,也可能不是。即使它不是,它也说明了Smalltalk的动态类型的强大功能。大量的魔法" Ruby on Rails是使用类似的策略构建的。这是可能的,因为Ruby对象与Smalltalk的对象有很多哲学相似之处。