Wednesday, April 06, 2005

Teaching Behavior

I cleaned up some old VisualWorks code I had from Ernest Micklei and published it to the Cincom Public Repository. Watch out for a "Teachable" package.
It's another nice example how powerfull Smalltalk really is. It's an implementation of a Teachable class who's instances can be teached to respond to messages. It's usefull for creating mocks who should behave like other objects (for instance inside of a test case) without actually implementing a real mock class. Here is an example how it can be used:

|teachable|
teachable := Teachable new.
teachable
    whenSend: #help return: 'ok';
    whenSend: #doit evaluate: [1 inspect];
    acceptSend: #noDebugger;
    whenSend: #negate: evaluate: [:num num negated].

After teaching the object we can use it as if it had a normal implementation in a class:

teachable help. "this will return the string 'ok'"
teachable doit. "this will open the inspector on the SmallInteger 1"
teachable noDebugger. "this will accept the send of #noDebugger and return the teachable"
teachable negate: 120 "this will return -120"

A Squeak version of the code can be found here.

2 comments:

Alexander Davis said...

I see you haven't posted much on Teachable lately (based on a search of your blog and Google), but I just tried using it and it's quite interesting!

My first comment was: "Oh, it'd be very interesting if there were a way to essentially create new variables in the object, not just methods.".

But of course, there is any easy way to simulate this!

----------------------------

fighter := Teachable new.
variables := Dictionary new.
fighter whenSend: #variables return: variables.
fighter variables at: #health put: 1.
fighter whenSend: #health evaluate: [fighter variables at: #health].
fighter whenSend: #health: evaluate: [:num| fighter variables at: #health put: num.].

fighter health.
fighter health: 10.

----------------------------

This is just a sample and can probably be cleaned up some, but you store the object's "variables" inside a dictionary, then have a way to return that dictionary (and thus add and remove new variables).

You can then create getter/setter methods that access the given "variable" just as a normal object. To an outside user, this will end up looking *exactly* the same (as if you had an instance variable in the traditional method, along with getter/setter).

So, anyway, yes, thank you for this! Very interesting. :)

- Alex

Alexander Davis said...

I see you haven't posted much on Teachable lately (based on a search of your blog and Google), but I just tried using it and it's quite interesting!

My first comment was: "Oh, it'd be very interesting if there were a way to essentially create new variables in the object, not just methods.".

But of course, there is any easy way to simulate this!

----------------------------

fighter := Teachable new.
variables := Dictionary new.
fighter whenSend: #variables return: variables.
fighter variables at: #health put: 1.
fighter whenSend: #health evaluate: [fighter variables at: #health].
fighter whenSend: #health: evaluate: [:num| fighter variables at: #health put: num.].

fighter health.
fighter health: 10.

----------------------------

This is just a sample and can probably be cleaned up some, but you store the object's "variables" inside a dictionary, then have a way to return that dictionary (and thus add and remove new variables).

You can then create getter/setter methods that access the given "variable" just as a normal object. To an outside user, this will end up looking *exactly* the same (as if you had an instance variable in the traditional method, along with getter/setter).

So, anyway, yes, thank you for this! Very interesting. :)

- Alex