<div dir="ltr"><div dir="ltr">On Tue, Jun 11, 2024 at 10:57 PM Vanessa Freudenberg via Cuis-dev <<a href="mailto:cuis-dev@lists.cuis.st">cuis-dev@lists.cuis.st</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">On Tue, Jun 11, 2024 at 4:29 PM Mark Volkmann via Cuis-dev <<a href="mailto:cuis-dev@lists.cuis.st" target="_blank">cuis-dev@lists.cuis.st</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr">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:<div><br></div><div><font face="monospace">doesNotUnderstand: aMessage<br>    "gets or sets an instance variable"<br><br></font><span style="font-family:monospace">   <span> </span></span><font face="monospace">| argCount getters key setters value |<br>     <br></font><span style="font-family:monospace">   <span> </span></span><font face="monospace">argCount := aMessage numArgs.<br></font><span style="font-family:monospace">   <span> </span></span><font face="monospace">argCount > 1 ifTrue: [ ^super doesNotUnderstand: aMessage ].<br><br></font><span style="font-family:monospace">   <span> </span></span><font face="monospace">key := aMessage keywords first.<br></font><span style="font-family:monospace">   <span> </span></span><font face="monospace">getters := self class allInstVarNames.<br></font><span style="font-family:monospace">   <span> </span></span><font face="monospace">setters := getters collect: [ :name | name, ':' ].<br></font><span style="font-family:monospace">   <span> </span></span><font face="monospace">(getters, setters includes: key) ifFalse: [ ^super doesNotUnderstand: aMessage ].<br>      <br></font><span style="font-family:monospace">   <span> </span></span><font face="monospace">argCount = 0 ifTrue: [ ^self perform: key ].<br>   <br></font><span style="font-family:monospace">   <span> </span></span><font face="monospace">value := aMessage arguments first.<br></font><span style="font-family:monospace">   <span> </span></span><font face="monospace">self perform: key with: value</font><br><div><br></div><div>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?</div></div></div></blockquote><div><br></div><div>Yes. The problem is that you don't have getters or setters implemented but you can only "perform" methods that exist.<br></div><div><br></div><div>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:".</div><div><br></div><div>Since you like the challenge I will not paste the "solution" here but put it in a gist</div><div><a href="https://gist.github.com/codefrau/3dc9e1a3020bb92864c57c4323041aec" target="_blank">https://gist.github.com/codefrau/3dc9e1a3020bb92864c57c4323041aec</a><br></div><div><br></div><div>–Nessa</div></div></div></blockquote><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div><font face="monospace">doesNotUnderstand: aMessage<br>    "gets or sets an instance variable"<br><br>    | argCount getters index key setters |<br>   <br>    argCount := aMessage numArgs.<br>    argCount > 1 ifTrue: [ ^super doesNotUnderstand: aMessage ].<br><br>    key := aMessage keywords first.<br> <br>    getters := self class allInstVarNames.<br>    index := getters indexOf: key.<br>    index ifNotZero: [^self instVarAt: index].<br>        <br>    setters := getters collect: [ :name | name, ':' ].<br>    index := setters indexOf: key.<br>    index ifNotZero: [^self instVarAt: index put: aMessage arguments first ].<br><br>    ^super doesNotUnderstand: aMessage</font><br></div><div><br></div></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div><font face="arial, helvetica, sans-serif">R. Mark Volkmann</font></div><div><span style="font-size:12.8px"><font face="arial, helvetica, sans-serif">Object Computing, Inc.</font></span></div></div></div></div></div></div></div></div></div>