Hi,
I'm writing a set of classes to represent something similar to a css, but for rtf files. I have 2 basic kind of text styles, paragraph styles and character styles. The problem is the same for both, so let's concentrate on character styles. I have a class called DefaultStyle, that represents the default formating for text. An instance of it may may be Times New Roman and 12 points. Now say I want a new style that represents bigger text, called BigStyle, which should inherit Times New Roman and overwrite 12 points with 16 points. So, it doesn't really inherit from the DefaultStyle class, but from an instance of it. This sounds odd and I suspect I have a design error. Any suggestions? |
Fernando,
> for text. An instance of it may may be Times New Roman and 12 points. Now > say I want a new style that represents bigger text, called BigStyle, which > should inherit Times New Roman and overwrite 12 points with 16 points. > > So, it doesn't really inherit from the DefaultStyle class, but from an > instance of it. > > This sounds odd and I suspect I have a design error. Any suggestions? I don't think you have anything to worry about; it's a common design pattern, and this seems like an appropriate application of it. You might even say that class-based inheritance is a special case of this general design, so don't let the word "inherit" worry you ;-) -- chris |
Hello Chris,
>> So, it doesn't really inherit from the DefaultStyle class, but from >> an instance of it. >> >> This sounds odd and I suspect I have a design error. Any >> suggestions? >> > I don't think you have anything to worry about; it's a common design > pattern, and this seems like an appropriate application of it. > > You might even say that class-based inheritance is a special case of > this general design, so don't let the word "inherit" worry you ;-) OK, but how do you inherit from an instance? O:-) |
Fernando,
> OK, but how do you inherit from an instance? O:-) Each instance contains a reference to its parent, which is also a Style (or nil). When you ask it for, say, the font-size, it looks to see if it holds a definition for that and if so answers the value. If not then it ask the parent (which in turn might ask its parent, and so on...). You can do that with hard-wired instvars (presumably using nil to indicate values that weren't set locally), or you could put a dictionary-like API on it (probably using a LookupTable internally in each Style object). Note that you wouldn't have a DefaultStyle class, you'd just have a Style class with one special instance which was held the defaults settings. All other instances would hold a different instance as their parent (possibly, but not necessarily, the default Style instance). Does that make sense ? -- chris |
Chris, Fernando
Wouldn't it be simpler to have just a Style class with DefaultFont and DefaultPointSize as class variables. Each newly created Style instance has its font and pointSize instvars set from the class defaults, and retains these values unless explicitly overridden. You might want to subclass Style if you wanted another family of styles with a different default, but normally the one class should be enough. Or have I misunderstood the problem? Best wishes Peter Kenny |
Peter,
> Wouldn't it be simpler to have just a Style class with DefaultFont and > DefaultPointSize as class variables. Each newly created Style instance has > its font and pointSize instvars set from the class defaults, and retains > these values unless explicitly overridden. That wouldn't work the same way. When you changed the master style (say) the derived styles wouldn't reflect the changes. E.g. if you changed the global font to Helvetica, paragraphs that just wanted to use a larger typeface would still have the old font. Whether Fernando needs that feature is, of course, a different question... BTW, another way (better IMO) to implement the pattern you described, is to have a "template" instance which holds the defaults, and then new instances are created by #copy-ing that. -- chris |
"Chris Uppal" <[hidden email]> wrote:
> That wouldn't work the same way. When you changed the master style (say) > the > derived styles wouldn't reflect the changes. Yes, I see - hadn't thought of that. So that is the point of your earlier suggestion that a Style instance might have its font instvar with a value of nil (because it had not been explicitly set), and the accessor method for font would do something like 'self class defaultFont' when it found a nil value. I suppose whether Style class>>defaultFont answers a class variable or copies the instvar of a template instance is largely irrelevant. Peter |
Peter,
> So that is the point of your earlier > suggestion that a Style instance might have its font instvar with a value > of nil (because it had not been explicitly set), and the accessor method > for font would do something like 'self class defaultFont' when it found a > nil value. Not exactly. That would be workable, but (for me) too inflexible since it limits you to exactly one level of derivation. E.g. I might want: #body-text is: font = arial size = 9pt colour = black #title-text is: derived from: #body-text size = 12pt #important-title-text is: derived from: #body-text colour = red So each "aspect" that wasn't set in one instance would be fetched by asking its parent for the value of the same aspect, which might well ask /its/ parent, and so on. There are very minor issues about how you terminate that process, but there are several ways to handle that (according to taste), and anyway that's just code... -- chris |
Hello Chris,
> Not exactly. That would be workable, but (for me) too inflexible > since it limits you to exactly one level of derivation. E.g. I might > want: > > #body-text is: > font = arial > size = 9pt > colour = black > #title-text is: > derived from: #body-text > size = 12pt > #important-title-text is: > derived from: #body-text > colour = red > So each "aspect" that wasn't set in one instance would be fetched by > asking its parent for the value of the same aspect, which might well > ask /its/ parent, and so on. That's exactly what I' looking for. However, I have the feeling of reinventing the wheel, as I'm reimplementing a kind of inheritance by hand... |
Fernando Rodríguez escribió:
> That's exactly what I' looking for. However, I have the feeling of > reinventing the wheel, as I'm reimplementing a kind of inheritance by > hand... Have in mind that inheritance is a concept, beyond the fact that Smalltalk uses it for its objects. Regards, -- Esteban. |
In reply to this post by Fernando Rodríguez
Fernando,
> That's exactly what I' looking for. However, I have the feeling of > reinventing the wheel, as I'm reimplementing a kind of inheritance by > hand... <Grin/> Yes, I see what you mean. But the mechanism used for class inheritance isn't really suitable for use here (unless you create classes on-the-fly), so you need a different implementation of roughly the same idea. (Now if you were using ECMAScript or SELF, then instance inheritance is built in to the language /instead/ of having class inheritance. That's an interesting idea, but it won't help you much here ;-) BTW, if I were doing this, I would be tempted to give my Style objects a Dictionary-like API, so the code that used them would say things like: color := aStyle styleAt: #Color. rather than: color := aStyle color. which would save a lot of messy duplication of the lookup code in each "aspect" of style (colour, font, size, etc). I might even create a general-purpose InheritingDictionary and use those inside, or instead of, the Style objects. -- chris |
Hello Chris,
> <Grin/> Yes, I see what you mean. But the mechanism used for class > inheritance isn't really suitable for use here (unless you create > classes on-the-fly), so you need a different implementation of roughly > the same idea. > > (Now if you were using ECMAScript or SELF, then instance inheritance > is built in to the language /instead/ of having class inheritance. > That's an interesting idea, but it won't help you much here ;-) Interesting idea, I'll try to check it out. > BTW, if I were doing this, I would be tempted to give my Style objects > a > Dictionary-like API, so the code that used them would say things like: > color := aStyle styleAt: #Color. > rather than: > color := aStyle color. > which would save a lot of messy duplication of the lookup code in each > "aspect" > of style (colour, font, size, etc). I might even create a > general-purpose InheritingDictionary and use those inside, or instead > of, the Style objects. That's a good idea, I'll give it a try. Thanks! :-) |
On Thu, 16 Mar 2006 16:04:41 +0000, Fernando Rodríguez wrote:
>> (Now if you were using ECMAScript or SELF, then instance inheritance is >> built in to the language /instead/ of having class inheritance. That's >> an interesting idea, but it won't help you much here ;-) > > Interesting idea, I'll try to check it out. And while you're at it, hop over to www.iolanguage.com, which is a nice, small and quite fast language for classless oop. Another thing, re: self. Somewhere on the 'net is a movie about self ... yes, there it is: http://www.merlintec.com:8080/Self So you were dead on with your feeling about reinventing the wheel. Good work, s. |
Hello Stefan,
> On Thu, 16 Mar 2006 16:04:41 +0000, Fernando Rodríguez wrote: > >>> (Now if you were using ECMAScript or SELF, then instance inheritance >>> is built in to the language /instead/ of having class inheritance. >>> That's an interesting idea, but it won't help you much here ;-) >>> >> Interesting idea, I'll try to check it out. >> > And while you're at it, hop over to www.iolanguage.com, which is a > nice, small and quite fast language for classless oop. Pretty cool. Before reading it, "classless oop" seemed crazy to me, but now I'm not sure if classes are really necessary at all... |
Free forum by Nabble | Edit this page |