6

I'm looking at this form an Objective-C background so be gentle. The experiment looks like this:

Object1 has an instance variable named delegate.

Object1 receives a message and the proceeds to check if delegate implements a specific protocol (whose name is known beforehand), if it does, then it checks if the message is among the protocol's implemented methods. It then makes a decision on how to interact with the delegate and so on.

In Objective-C one has to define clear Protocols, usually stored in different files, and conforming to a protocol is checked by the compiler. In Pharo I can't seem to find how to check for this kind of information even though the Browser has a whole column dedicated to protocols, and beside grouping methods they seem to do very little.

unom
  • 11,438
  • 4
  • 34
  • 54
  • 1
    I don't know much about "protocols" in Objective-C, but you're right, in Smalltalk they're not much more than a way to group methods (a.k.a. "categories"). There are conventions about how to define these protocols, and which methods typically go in which protocol, but they're just, well, conventions. You can ask a class for `#allMethodsInCategory:`, but unless I'm misunderstanding you, I don't think that's what you're after, because it sounds like they're something entirely different in Objective-C. Leandro's answer gives you some options for checking which methods an object responds to. – Amos M. Carpenter Sep 09 '15 at 04:49
  • 1
    @AmosM.Carpenter That was exactly what I was looking for, found it myself while searching for something else. There was a method #allMethodsInCategory: that has been deprecated in Pharo 3.0 and later in favor of #allSelectorsInProtocol: which does what I want. See http://stackoverflow.com/questions/2990966/how-can-i-get-all-the-methods-in-a-protocol Some other dialects have methodsInProtocol: all the same. – unom Sep 10 '15 at 13:34

2 Answers2

7

Here are some few alternatives that could help you with this:

  1. Get the collection of all selectors that populate the object's class:
    • anObject class selectors
  2. Get the collection of all selectors that populate the object's class and all its superclasses:
    • anObject class allSelectors
  3. Ask the class whether it implements a given message (for its instances):
    • anObject class canUnderstand: #putTheSelectorHere
  4. Ask the object whether it understands a given message:
    • anObject respondsTo: #methodSelectorHere
  5. Use the MessageNotUnderstood mechanism:
    • (see explanation below)

In 1 and 2 above you can use the returned collections to check whether they include a certain selector you are interested in. Features 3, 4 and 5 have a more dynamic nature. For example, you can refine the #doesNotUnderstand: method in your class as follows:

MyClass >> #doesNotUnderstand: aMessage
    (delegate respondsTo: aMessage selector)
        ifTrue: [^delegate
           perform: aMessage selector
           withArguments: aMessage arguments].
    ^super doesNotUnderstand: aMessage

This way, if your object receives a message that it does not understand, it will first receive the #doesNotUnderstand: message (without you having to do anything for this to happen) and here you could decide (e.g., by using the #respondsTo: message) whether to delegate it or not. If not, you can just relay on the default behavior (super doesNotUnderstand:) which would signal de MessageNotUnderstood exception.

Of course, there is a 6th option, which would be for the sender of the message to handle the MNU exception, but I don't think this is what you are looking for here.

Leandro Caniglia
  • 14,495
  • 4
  • 29
  • 51
  • From what I see: #doesNotUnderstand is called after a method for the selector couldn't be found. So I would be getting the overhead of that with every message, and also I can't forward basic Object selectors, since both the redirector and the delegate are Objects and the redirector would only forward if it doesn't understand. Objective-C has forwardInvocation: which forwards absolutely everything even before method lookup takes place. Do we have that in Smalltalk? – unom Sep 06 '15 at 21:58
  • @unmircea I probably misunderstood your question. Perhaps you could edit it so to help us understand better what you are trying to do. – Leandro Caniglia Sep 07 '15 at 14:57
  • @LeandroCaniglia Managed to find the answer, there was a method allMethodsInCategory: that has been deprecated in Pharo 3.0 and later in favor of allSelectorsInProtocol: which does what I want. Add this to the answer and I'll accept it, it's very detailed so thank you! See here: http://stackoverflow.com/questions/2990966/how-can-i-get-all-the-methods-in-a-protocol Some other dialects have methodsInProtocol: all the same. – unom Sep 09 '15 at 22:07
  • 1
    @StephanEggermont Good papers, Instance method wrappers seem to be a cool way to do what I want. Thank you! They were mentioned in a comment on an older question of mine and I managed to overlook them. http://stackoverflow.com/questions/28225725/pharo-smalltalk-message-forwarding-is-it-possible-to-intercept-a-message-and – unom Sep 09 '15 at 22:11
3

There is the proxies work in Ghost/Marea and the original Smalltalk wrappers to the rescue I'm not sure the proxies have been updated for the latest Pharo version. Latest ghost version seems to be here

Stephan Eggermont
  • 15,847
  • 1
  • 38
  • 65
  • Thanks for the fast response... I was looking for something more direct like the Obj-C [[myObject class] conformsToProtocol:@protocol(MyProtocol)]; that would be supported out of the box, something along the lines of myObject class conformsToProtocol:'Whatever'. – unom Sep 06 '15 at 14:47