[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