VitorCruz
VitorCruz

Reputation: 421

Delegation in Pharo Smalltalk

What is the best way of doing delegation in Smalltalk, more specifically in Pharo? I know of the doesNotUnderstand strategy, but it does not delegates subclassResponsability messages.

I was thinking on something that delegates every message send not explicitly implemented on the class to some specified object, like I can do, for example, with @Delegate in Groovy. Is there some already known way of doing this?

Upvotes: 2

Views: 452

Answers (2)

Nicolai Hess
Nicolai Hess

Reputation: 376

what Peter was talking about is, you can override the subclassResponsibility, just like you did for the doesNotUnderstand method. There is no need to override every senders of "self subclassResponsibility".

For example, just delegate to the implementation of doesNotUnderstand

subclassResponsibility

^ self
    doesNotUnderstand: (Message selector: thisContext sender selector 
                                arguments: thisContext sender arguments)

Upvotes: 2

Peter Uhnak
Peter Uhnak

Reputation: 10217

doesNotUndersand: will only work on methods that the object does not understand (thus the name), so if you already have implemented a method it will not be used (as is the case with subclassResponsibility.

If you use Pharo 5 (which should be released this week (May 2016)), you could use MetaLinks. It's a bit of an overkill, however what you are doing doesn't seem right to begin with (why would you want to delegate subclassResponsibility)?

In either case, MetaLinks allow to attach runtime behavior to your methods, for example:

You have some method that you want to delegate

MyObject>>someMethod
    ^ self subclassResponsiblity

And an object to which you wish to delegate to…

MyObject>>delegate
    ^ delegate

So you create a MetaLink

link := MetaLink new
    metaObject: [ :object :selector :arguments |
        object delegate perform: selector withArguments: argument ];
    selector: #perform:withArguments:;
    arguments: #(object selector arguments);
    control: #instead.

Which you can install to any method AST you want.

(MyObject>>someMethod ast) link: link.

Now every time the method will be called, instead (that's what the control: does) of executing the method, the arguments of the message (if any) will be given to the block in metaObject:.

Although this should work and is extremely powerful mechanism, right now there are serious disadvantages that currently being addressed:

  • no documentation
  • little tooling support (it's pretty hard to debug)
  • a lot of work (we are working on a framework that would ease this as you would want to easily install them and uninstall them everywhere you need, but it's not ready yet, so it has to be done by hand)
  • recompilation removes the link (see point above)

Summary

To summarize, this is possible to do with MetaLinks as I've shown, however at the moment it's quite a lot of work, but we are addressing those issues.

Upvotes: 3

Related Questions