简体   繁体   English

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

[英]How to specify class for instance variable in smalltalk

Probably I haven't understood the concepts of smalltalk enough, but here is my problem: 可能我对小话的概念还不够了解,但这是我的问题:

I am creating a class, let's call it Main-class , that has an instance variable bar , that I want to be of a certain class - Other-class , and use this Other-class ' methods on that in the Main-class methods kind of like this: 我正在创建一个类,我们将其称为Main-class ,它具有一个实例变量bar ,我想成为某个类-Other-class ,并在Main-class方法中使用该Other-class '方法有点像这样:

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

setFoo: newFoo

    foo := newFoo.

And the Main-class : 主班

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

newBar: val

    bar := Bar new. 
    bar setFoo: val.

Obviously, I get an error that there is no setFoo method. 显然,我收到一个没有setFoo方法的错误。 But how do I specify that I want bar to be variable of a specific class and then use that class' methods on it? 但是,如何指定我希望bar成为特定类的变量,然后在其上使用该类的方法呢?

Concerning the question's title: you don't. 关于问题的标题:您没有。 Smalltalk is a dynamically typed language, which means that the value of a variable can have different types at different points in time -- types are not declared for variables. Smalltalk是一种动态类型化的语言,这意味着变量的值在不同的时间点可以具有不同的类型-不会为变量声明类型。 But for humans, you can note the actual types of the variables in the class comment (see the ? button next to the instance-side and class-side buttons in the system browser). 但是对于人类来说,您可以在类注释中记录变量的实际类型(请参阅系统浏览器中实例侧和类侧按钮旁边的?按钮)。

Concerning your problem: You have to make sure that the object that is assigned to the instance variable bar is of a suitable type. 关于您的问题:您必须确保分配给实例变量bar的对象具有适当的类型。 In this case it must understand the message setFoo: . 在这种情况下,它必须了解消息setFoo: In your second code snippet, this means either: 在第二个代码段中,这意味着:

  1. that instead of Bar you should use another class that can respond to setFoo: , such as Other-class (which is an odd name by the way because of the hyphen, you cannot easily reference that in your methods, use CamelCase instead), to fill the variable, or 而不是Bar您应该使用另一个可以响应setFoo: Other-class ,例如Other-class (由于连字符,这是一个奇怪的名称,您不能轻易地在方法中引用它,而使用CamelCase),填写变量,或
  2. that setFoo: must be implemented for the class Bar . setFoo:必须为Bar类实现。

The respondsTo: method can be used to determine if an object responds to a message: respondsTo:方法可用于确定对象是否响应消息:

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

If you don't want to launch the missiles when bar does not understand setFoo , then decide what you want to happen. 如果您不希望在bar不了解setFoo时发射导弹,请决定要发生什么。 Maybe your program should crash with an error. 也许您的程序应该因错误而崩溃。 That's less extreme than launching the missiles, but still kind of extreme and rarely what you really want particularly if other people are using your software. 这并不比发射导弹来得极端,但仍然是一种极端,很少真正需要的,尤其是在其他人正在使用您的软件的情况下。

Option: Just use the right type of object 选项:仅使用正确类型的对象

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

Option: extend the object to do what you need by modifying its Class 选项:通过修改对象的类来扩展对象以执行所需的操作

ifFalse: [ (bar class) addInstVarName: 'foo'.
           (bar class) compile: 'setFoo: newFoo [foo := newFoo]'.
           bar setFoo: val. ]

The second option may or may not be what you want to do depending on context. 根据上下文,第二个选项可能是也可能不是您想要执行的操作。 Even if it isn't, it illustrates the power of Smalltalk's dynamic typing. 即使不是,它也说明了Smalltalk动态键入的强大功能。 A good deal of the "magic" of Ruby on Rails is built using a similar strategy. Ruby on Rails的很多“魔术”都是使用类似的策略构建的。 It is possible because Ruby objects have a lot of philosophical similarity to Smalltalk's objects. 这是可能的,因为Ruby对象与Smalltalk对象具有很多哲学上的相似之处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM