[Cuis-dev] clever or silly idea?

Mark Volkmann r.mark.volkmann at gmail.com
Wed Jun 12 06:35:26 PDT 2024


On Tue, Jun 11, 2024 at 10:57 PM Vanessa Freudenberg via Cuis-dev <
cuis-dev at lists.cuis.st> wrote:

> On Tue, Jun 11, 2024 at 4:29 PM Mark Volkmann via Cuis-dev <
> cuis-dev at lists.cuis.st> wrote:
>
>> A thought occurred to me that I could override the instance method
>> `doesNotUnderstand` in a class to avoid writing a bunch of basic accessor
>> methods. Setting aside whether it's ever a good idea to have a getter and
>> setter method for every instance variable in a class, I thought I could do
>> it like this:
>>
>> doesNotUnderstand: aMessage
>>     "gets or sets an instance variable"
>>
>>     | argCount getters key setters value |
>>
>>     argCount := aMessage numArgs.
>>     argCount > 1 ifTrue: [ ^super doesNotUnderstand: aMessage ].
>>
>>     key := aMessage keywords first.
>>     getters := self class allInstVarNames.
>>     setters := getters collect: [ :name | name, ':' ].
>>     (getters, setters includes: key) ifFalse: [ ^super
>> doesNotUnderstand: aMessage ].
>>
>>     argCount = 0 ifTrue: [ ^self perform: key ].
>>
>>     value := aMessage arguments first.
>>     self perform: key with: value
>>
>> But this goes into an infinite loop because sending the `perform:`
>> message ends up hitting `doesNotUnderstand` again. Is there a way I could
>> make this work?
>>
>
> Yes. The problem is that you don't have getters or setters implemented but
> you can only "perform" methods that exist.
>
> You need a different way to access the instance variables. You could use
> the same methods that the debugger uses to get and set the instance
> variables: "instVarAt:" and "instVarAt:put:".
>
> Since you like the challenge I will not paste the "solution" here but put
> it in a gist
> https://gist.github.com/codefrau/3dc9e1a3020bb92864c57c4323041aec
>
> –Nessa
>

Thanks so much Nessa! I didn't know about `instVarAt:` and
`instVarAt:put:`. I expanded on your approach by creating an `Accessible`
class. Any class can inherit from that to make all its instance variables
accessible. Below is my `doesNotUnderstand:` method in the `Accessible`
class. I think it only differs from yours in my use of `ifNotZero:`.
Probably not a good idea to use this, but it was a fun exercise.

I also learned this morning that I can right-click a class in a System
Browser window and select more ... create inst var accessors to generate
accessor methods for every instance variable.

doesNotUnderstand: aMessage
    "gets or sets an instance variable"

    | argCount getters index key setters |

    argCount := aMessage numArgs.
    argCount > 1 ifTrue: [ ^super doesNotUnderstand: aMessage ].

    key := aMessage keywords first.

    getters := self class allInstVarNames.
    index := getters indexOf: key.
    index ifNotZero: [^self instVarAt: index].

    setters := getters collect: [ :name | name, ':' ].
    index := setters indexOf: key.
    index ifNotZero: [^self instVarAt: index put: aMessage arguments first
].

    ^super doesNotUnderstand: aMessage

-- 
R. Mark Volkmann
Object Computing, Inc.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20240612/a7267f46/attachment-0001.htm>


More information about the Cuis-dev mailing list