简体   繁体   English

如何在Smalltalk中在运行时向类添加方法?

[英]How can I add methods to a class at runtime in Smalltalk?

I'm building a Smalltalk API to an XML-based web service. 我正在为基于XML的Web服务构建Smalltalk API。 The XML service is so regular that, rather than write the methods by hand, I figured I'd just override #doesNotUnderstand: to dynamically add methods via MyApi class>>compile: , then call all the methods once in a workspace, then remove the DNU and have my nice API. XML服务非常规则,而不是手工编写方法,我想我只是覆盖#doesNotUnderstand:通过MyApi class>>compile:动态添加方法MyApi class>>compile: ,然后在工作区中调用所有方法一次,然后删除DNU并拥有我不错的API。

This works great, but passing a giant string to #compile: just feels really wrong to me; 这很好用,但将一根巨大的字符串传递给#compile:对我来说感觉真的很不对劲; in Python and other languages, I'd be able to attach a nicely syntax-checked lambda to a class to achieve a similar effect in a safer manner. 在Python和其他语言中,我能够将一个很好的语法检查的lambda附加到一个类,以更安全的方式实现类似的效果。 Eg: 例如:

def himaker(name):
    def hello(self, times):
        for x in xrange(times):
            print "Hi, %s!" % name
    return hello
class C(object): pass
C.bob = himaker('Bob')
C.jerry = himaker('Jerry')
a = C()
a.bob(5)

versus

SomeObject>>addHello: name
    | source methodName |
    methodName := 'sayHello', name, 'Times:'.
    source := String streamContents: [ :s |
         s nextPutAll: methodName, ' count'.
         s nextPut: Character cr.
         s nextPut: Character tab.
         s nextPutAll: 'count timesRepeat: [ Transcript show: ''Hi, ', name, '!'' ].' ]
    SomeObject class compile: source

Surely there must be something as clean as the Python version? 当然必须有像Python版本一样干净的东西?

If you just want the source string to more clearly reflect the method: 如果您只是希望源字符串更清楚地反映该方法:

SomeObject>>addHello: name
  | methodTemplate methodSource |
  methodTemplate := 'sayHello{1}Times: count
  count timesRepeat: [ Transcript show: ''Hi, {1}!'' ].'.   
  methodSource := methodTemplate format: { name }.
  self class compile: methodSource.

If you want the source to be syntax-checked, you could start with a template method like this: 如果您希望对源进行语法检查,可以从这样的模板方法开始:

sayHelloTemplate: count
    count timesRepeat: [ Transcript show: 'Hi, NAME' ].

And then fill the template accordingly, like: 然后相应地填写模板,例如:

addHello2: name
    | methodTemplate methodSource |
    methodTemplate := (self class compiledMethodAt: #sayHelloTemplate:) decompileWithTemps.
    methodTemplate selector: ('sayHello', name, 'Times:') asSymbol.
    methodSource := methodTemplate sourceText copyReplaceAll: 'NAME' with: name.
    self class compile: methodSource.

Of course, all of this would be clearer if some methods were extracted :) 当然,如果提取了一些方法,所有这些都会更清楚:)

Suppose you have template method: 假设你有模板方法:

SomeClass>>himaker: aName
  Transcript show: 'Hi ...'

Then you can copy it to other class, just don't forget to set selector and class if you don't want to confuse the system browser. 然后你可以将它复制到其他类,如果你不想混淆系统浏览器,不要忘记设置选择器和类。 Or if you don't care, that just install the copy at method dictionary. 或者,如果您不在乎,只需在方法词典中安装副本即可。

| method |

method := (SomeClass>>#himaker:) copy.

method methodClass: OtherClass.
method selector: #boo: .
OtherClass methodDict at: #boo: put: method.

method := method copy.
method selector: #bar: .
method methodClass: OtherClass2.
OtherClass2 methodDict at: #bar: put: method.

Well, compile: takes a String. 好吧,编译:接受一个字符串。 If you want something more typesafe, you could build a parsetree and use that. 如果你想要更安全的东西,你可以构建一个parsetree并使用它。

I would use block: 我会用块:

himaker := [:name | [:n | n timesRepeat: [Transcript show: 'Hi , ', name, '!']]]
hibob = himaker value: 'bob'.
hialice = himaker value: 'alice'.
hialice value: 2

You can still make himaker a method 你仍然可以使himaker成为一种方法

himaker: name
    ^[:n | n timesRepeat: [Transcript show: 'Hi, ', name, '!']]

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

相关问题 在Smalltalk中在运行时向对象添加特征 - Add trait to object at runtime in Smalltalk 我如何在Smalltalk中换行? - How can i get a new line in smalltalk? Pharo Smalltalk-如何检查消息是否符合另一个对象的Class中定义的协议? - Pharo Smalltalk - How can I check if a message conforms to a protocol defined in another object's Class? 在Smalltalk中,如何在类B的实例上从类A内调用类B中的访问器方法? - In Smalltalk, how do you invoke accessor methods in Class B from within Class A on an instance of class B? Cincom Visualworks Smalltalk-类方法初始化 - Cincom Visualworks Smalltalk - Class Methods Initialization 如何在Smalltalk Squeak / Pharo中轻松更改为原生字体 - How can I easily change to native fonts in Smalltalk Squeak/Pharo 如何在Smalltalk中使用该方法进行编译以及可以使用哪些参数进行调用 - How to use the method compile in smalltalk and what parameters can I call it with visualworks smalltalk:如何从字符串中检测 substring,这可能吗? - visualworks smalltalk: how can I detect substring from a string, is it possible? 如何在Smalltalk中创建类的实例? - How to make instances of a class in Smalltalk? 如何在Smalltalk的范围内生成随机整数? - How can I generate random integers in a range in Smalltalk?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM