I do not know if others have this problem, but I find it hard to
extend the class PrintConverter. For example I have a Currency class, which overrides the class method for: PrintConverter class>>for: aSymbol ... aSymbol == #currency ifTrue: [^converter initForCurrency]. ... and: PrintConverter class>>for: aSymbol withFormatString: aString ... aSymbol == #currency ifTrue: [^self new initForCurrencyWithFormat: aString]. ... However, other packages I have also need to add things to these methods, which creates an override hell, not to mention that publishing a package with overrides is not allowed. So, did anyone find a solution for this, and could the class maybe be improved to allow extensions from applications? |
No real help from me -- but I looked at PrintConverter, and wrote my own
set of converter classes (a whole set of them) -- and treat all my fields on GUI's as strings and do my own conversions in my subclass of AspectConverter. Took a bit of time to get started, but in the long run it was simpler I think. Unfortunately my classes are tied pretty strongly into other concepts in our applications but basically I had one class for each data type, and dispatched it from the class side. Rob Vens wrote: > I do not know if others have this problem, but I find it hard to > extend the class PrintConverter. > For example I have a Currency class, which overrides the class method > for: > PrintConverter class>>for: aSymbol > ... > aSymbol == #currency ifTrue: [^converter initForCurrency]. > ... > > and: > PrintConverter class>>for: aSymbol withFormatString: aString > ... > aSymbol == #currency > ifTrue: [^self new initForCurrencyWithFormat: aString]. > ... > > However, other packages I have also need to add things to these > methods, which creates an override hell, not to mention that > publishing a package with overrides is not allowed. > So, did anyone find a solution for this, and could the class maybe be > improved to allow extensions from applications? > -- Dennis Smith +1 416.798.7948 Cherniak Software Development Corporation Fax: +1 416.798.0948 509-2001 Sheppard Avenue East [hidden email] Toronto, ON M2J 4Z8 sip:[hidden email] Canada http://www.CherniakSoftware.com Entrance off Yorkland Blvd south of Sheppard Ave east of the DVP |
In reply to this post by Rob Vens-2
This sounds like a job for Pragmas.
In PrintConverter, define a new class method: formatPragma <pragmas: #class> ^#(#format:send:) Now, in the PrintConverter >> for:withFormatString: method, add the following before the last line: (Pragma allNamed: #format:send: in: self class) do: [:pragma | pragma withArgumentsDo: [:formatString :selector | aSymbol == formatString ifTrue: [^self new perform: selector with: aString]]]. Now, you can extend the PrintConverter to your heart's content. Any time you want to add a new converter, extend PrintConverter and add a method like this: sampleExtendedFormat <format: #sample send: #initForSample:> Now, define initForSample: as an extension as well and get it to do the formatting you want. David Buck Simberon Inc. www.simberon.com Rob Vens wrote: > I do not know if others have this problem, but I find it hard to > extend the class PrintConverter. > For example I have a Currency class, which overrides the class method > for: > PrintConverter class>>for: aSymbol > ... > aSymbol == #currency ifTrue: [^converter initForCurrency]. > ... > > and: > PrintConverter class>>for: aSymbol withFormatString: aString > ... > aSymbol == #currency > ifTrue: [^self new initForCurrencyWithFormat: aString]. > ... > > However, other packages I have also need to add things to these > methods, which creates an override hell, not to mention that > publishing a package with overrides is not allowed. > So, did anyone find a solution for this, and could the class maybe be > improved to allow extensions from applications? > > |
Thanks, David, I should have thought of that! I will try it out
immediately. I must admit that employing the pragmas has been neglected by me so this seems a good reason to do just that. 2007/4/15, David Buck <[hidden email]>: > This sounds like a job for Pragmas. > > In PrintConverter, define a new class method: > > formatPragma > <pragmas: #class> > ^#(#format:send:) > > Now, in the PrintConverter >> for:withFormatString: method, add the > following before the last line: > > (Pragma allNamed: #format:send: in: self class) do: > [:pragma | > pragma withArgumentsDo: > [:formatString :selector | aSymbol == formatString ifTrue: > [^self new perform: selector with: aString]]]. > > Now, you can extend the PrintConverter to your heart's content. Any > time you want to add a new converter, extend PrintConverter and add a > method like this: > > sampleExtendedFormat > <format: #sample send: #initForSample:> > > Now, define initForSample: as an extension as well and get it to do the > formatting you want. > > David Buck > Simberon Inc. > www.simberon.com > > Rob Vens wrote: > > I do not know if others have this problem, but I find it hard to > > extend the class PrintConverter. > > For example I have a Currency class, which overrides the class method > > for: > > PrintConverter class>>for: aSymbol > > ... > > aSymbol == #currency ifTrue: [^converter initForCurrency]. > > ... > > > > and: > > PrintConverter class>>for: aSymbol withFormatString: aString > > ... > > aSymbol == #currency > > ifTrue: [^self new initForCurrencyWithFormat: aString]. > > ... > > > > However, other packages I have also need to add things to these > > methods, which creates an override hell, not to mention that > > publishing a package with overrides is not allowed. > > So, did anyone find a solution for this, and could the class maybe be > > improved to allow extensions from applications? > > > > > > |
Just to clarify, these are all class methods except for initFotSample:
which is an instance method. David Buck Rob Vens wrote: > Thanks, David, I should have thought of that! I will try it out > immediately. I must admit that employing the pragmas has been > neglected by me so this seems a good reason to do just that. > > 2007/4/15, David Buck <[hidden email]>: >> This sounds like a job for Pragmas. >> >> In PrintConverter, define a new class method: >> >> formatPragma >> <pragmas: #class> >> ^#(#format:send:) >> >> Now, in the PrintConverter >> for:withFormatString: method, add the >> following before the last line: >> >> (Pragma allNamed: #format:send: in: self class) do: >> [:pragma | >> pragma withArgumentsDo: >> [:formatString :selector | aSymbol == formatString ifTrue: >> [^self new perform: selector with: aString]]]. >> >> Now, you can extend the PrintConverter to your heart's content. Any >> time you want to add a new converter, extend PrintConverter and add a >> method like this: >> >> sampleExtendedFormat >> <format: #sample send: #initForSample:> >> >> Now, define initForSample: as an extension as well and get it to do the >> formatting you want. >> >> David Buck >> Simberon Inc. >> www.simberon.com >> >> Rob Vens wrote: >> > I do not know if others have this problem, but I find it hard to >> > extend the class PrintConverter. >> > For example I have a Currency class, which overrides the class method >> > for: >> > PrintConverter class>>for: aSymbol >> > ... >> > aSymbol == #currency ifTrue: [^converter initForCurrency]. >> > ... >> > >> > and: >> > PrintConverter class>>for: aSymbol withFormatString: aString >> > ... >> > aSymbol == #currency >> > ifTrue: [^self new initForCurrencyWithFormat: aString]. >> > ... >> > >> > However, other packages I have also need to add things to these >> > methods, which creates an override hell, not to mention that >> > publishing a package with overrides is not allowed. >> > So, did anyone find a solution for this, and could the class maybe be >> > improved to allow extensions from applications? >> > >> > >> >> > > |
On Apr 15, 2007, at 7:36, David Buck wrote:
This is cool David. Indeed. Looking it at, it seems one could go even farther. Rather than having the class side sampleExtendedFormat method... I think I would just add an instance tag (pragma) to the initForSample: method, and search for and call that directly at the end of for:withFormatString: You'd have half as many methods and a more direct linkage. This is indeed a neat way to use tagged methods. That said though, I was horrified by the method in the first place. It is a huge case statement. And what we seem to be doing here is making the case statement extensible. Even when we use tags to make it pluggable, it's still a case statement. There's a sense of "use the method Luke" that I find myself mumbling looking at this code. Rather than PrintConverter for: #currency withFormatString: 'blah' wouldn't it just be better to do: PrintConverter currency withFormatString: 'blah'. I admit to not messing directly with these things often, so maybe I'm missing something. But this seems far better. It is instantly "extendible", because you just add a new method for creating PrintConverters of a new type. And it does so by getting rid of indirection, removing tags (pragmas), removing case statements, etc. You could put this pattern in place without even having to modify the existing thing. After that... one might argue that it would be better to just have typified subclasses. So that in the end you can send: StringConverter withFormatString: 'blah'. There is no "technical" reason one was to go the subclass route, because the Converters are just bags of blocks with state closed directly in the initMethods. But even with empty subclasses, I think the interface would be that much clearer, the possibilities are higher (you could indeed add instance state), and the code you input to interface with them is less and more direct. I'm ambivalent on the subclasses thing, but I do think that it's better to send messages, instead of passing symbols that look kind of like the messages they're going to turn into, but not exactly. -- Travis Griggs Objologist My Other Machine runs OSX. But then... so does this one. |
Free forum by Nabble | Edit this page |