DoesNotUnderstand: a Precious Hook

Damien Cassou, Stéphane Ducasse and Luc Fabresse http://stephane.ducasse.free.fr

When No Method is Found

doesNotUnderstand: is a Message

Example 1: Delegation

Redirect unknown messages to another object (a target)

Example 1: Delegation

Object subclass: #Delegating
   instanceVariableNames: 'target'
Delegating >> doesNotUnderstand: aMessage
   ^ aMessage sendTo: self target

Example 2: A LoggingProxy

Basic idea:

Implementing LoggingProxy

ProtoObject subclass: #LoggingProxy
	instanceVariableNames: 'subject invocationCount'
	classVariableNames: ''
	package: 'LoggingProxy'
LoggingProxy >> initialize 
	invocationCount := 0. 
	subject := self
	"will be swapped by become:"

Customize doesNotUnderstand:

LoggingProxy >> doesNotUnderstand: aMessage
	Transcript show: 'performing ', aMessage printString; cr.
	invocationCount := invocationCount + 1.
	^ aMessage sendTo: subject
Message >> sendTo: receiver
   ^ receiver perform: selector withArguments: args

Message Behavior

| point |
point := 1@2.
LoggingProxy new become: point.
self assert: point invocationCount = 0.
self assert: point x + point y = 3.
self assert: point + (3@4) = (4@6).
self assert: point invocationCount = 3.

Some Limits of such Minimal Objects

Another Application

Scaffolding patterns: Generate code on the fly based of patterns

DynamicAccessors >> doesNotUnderstand: aMessage
   | messageName |
   messageName := aMessage selector asString.
   (self class instVarNames includes: messageName)
      ifTrue: [self class compile:
                  messageName , String cr , ' ^ ' , messageName.
         ^ aMessage sendTo: self].
   super doesNotUnderstand: aMessage

Conclusion

Minimal Objects

doesNotUnderstand:

/