Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interception messages in Squeak

I am trying to understand better reflection in Smalltalk. I am using the latest version of Squeak (v4.3). I want to intercept every message sent to instances of one of my classes. I assumed that I could override the method ProtoObject>>withArgs:executeMethod but Stéphane Ducasse explained me that for performance reason, this method is not used (this is my own summary of his answer). Which method should I override / how could intercept sent messages?

Here is the code of my attempt:

Object subclass: #C
    instanceVariableNames: 'i'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'CSE3009'.

C class compile: 'newWithi: anInt
    ^(self new) i: anInt ; yourself.'.

C compile: 'withArgs: someArgs executeMethod: aMethod
    Transcript show: ''Caught: ''.
    ^ super withArgs: someArgs executeMethod aMethod.'.

C compile: 'foo: aText
    Transcript show: aText.
    Transcript show: i.
    Transcript cr.'.

C compile: 'i: anInt
    i := anInt.'.

o := C newWithi: 42.
o foo: 'This is foo: '.

Executing this entire piece of code yields:

This is foo: 42

When I would like to have:

Caught: This is foo: 42
like image 288
Yann-Gaël Guéhéneuc Avatar asked Apr 12 '13 15:04

Yann-Gaël Guéhéneuc


1 Answers

There's no build-in way to intercept messages to objects like that. There are two ways we commonly use to do this kind of trick.

First, you can create a wrapper object which responds to doesNotUnderstand:. This object usually has nil for the superclass so it doesn't inherit any instance methods from Object. The doesNotUnderstand: handler would delegate all its messages to the target object. It has the option of performing code before and after the call. All references to the original object would now point to the new "proxy" object. Messages to self wouldn't be intercepted and the proxy would need to test for objects that return self and change the returned object to be the proxy instead.

The second approach is to use a mechanism called Method Wrappers. Method Wrappers allows you to replace all of the methods in a set of classes with methods that do some other operations before and after calling the original method. This approach can provide fairly seemless results and intercepts all messages including those send to self.

MethodWrappers is available for VisualWorks and VASmalltalk. I believe it's also available for Squeak and Pharo but I'm not positive.

like image 189
David Buck Avatar answered Oct 01 '22 03:10

David Buck