Does Not Understand

The run-time complaint issued by SmalltalkLanguage when a receiver is asked to perform a method that is unknown to it.


When a Smalltalk object is sent a message for a method it has not defined, the runtime system turns the message-send into an object (with accessors for things like the selector and arguments) and sends #doesNotUnderstand: to the original receiver with this message-send object as argument. By default the #doesNotUnderstand: method raises an exception, but the receiver can override it (in the usual way) to forward the message-send to a different receiver, log it in a file, add it to a FIFO queue for later processing, or whatever.

In effect you can partially redefine the semantics of message-sending. Since almost everything in the SmalltalkLanguage is done by sending messages, this is a very general and powerful feature.


It is crucial that the complaint is given to the receiver not the sender. In JavaLanguage or CeePlusPlus you can write things like:

try {
((Receiver) anObject).message();
} catch (ClassCastException e) {
anObject.doesNotUnderstand( new MessageSend( "message" ) );
}
which roughly captures the intent, but this is clearly rather verbose and it has to be repeated for every call. It is impractical even if you get the compiler to generate this code for you.


You can do the same trick if the receiver is CeePlusPlus and the sender VisualBasic. Implement IDispatch::GetIDsOfNames. -- FrederickKoh?


Combined with #become:, which causes two objects to trade places in memory, this capability of #doesNotUnderstand: is very useful for implementing ProxyObject?s such as are needed in ObjectRelationalMapping frameworks. Try that in JavaLanguage.

Overriding #doesNotUnderstand: on RoleObjects is also an efficient way to implement the RoleAndPlayer pattern in SmallTalk.

-- RandyStafford


The equivalent of #doesNotUnderstand: in the CommonLispObjectSystem is the GenericFunction no-applicable-method (see section 7.6.6 of the CommonLispHyperSpec). no-applicable-method is invoked if a generic function is called and no methods are applicable, and the results from that call are used as the results of the call to the original generic function. no-applicable-method is not intended to be called by the user, but he may write methods for it. The default method signals an error.


Someone claimed DoesNotUnderstand was only for errors, and that it was an unnatural act to use it for any other purpose.

But it is a standard idiom in the SmalltalkLanguage to use #doesNotUnderstand: to implement forwarding, delegation, proxies etc.

Example: The Smalltalk FAQ: http://www.faqs.org/faqs/smalltalk-faq/

Example: Discussed as one of the ways to do reflection in the classic paper "Reflective Facilities in Smalltalk-80" http://www.laputan.org/ref89/ref89.html

The counter-argument to this is that this is a trick similar to using exceptions for non-error control structures; despite being a standard idiom, it still can be dangerous if done improperly, and can be more difficult to implement, understand, and debug. Other languages such as ObjectiveCee provide explicit mechanisms for delegation and method lookup for reflection, allowing its equivalent of DoesNotUnderstand to be used only for errors.

A blog entry critiques a kind of varargs (with:with:with:with...) implemented via DoesNotUnderstand: http://www.cincomsmalltalk.com/userblogs/buck/blogView?showComments=true&entry=3264795091

As with proxying, it could be argued that just adding a more explicit varargs somehow would be better than this use of DoesNotUnderstand.


RubyLanguage has an equivalent of #doesNotUnderstand named #method_missing:

>> def method_missing *args
>>  p args
>> end
=> nil
>> foo 1,2,3,4
[:foo, 1, 2, 3, 4]
=> nil
-- GabrieleRenzi


MartinFowler describes this as DynamicReception

-- JamesMead


CategorySmalltalk


EditText of this page (last edited September 8, 2009) or FindPage with title or text search