Java Forum / First Aid / September 2005
Reaching a indirect superclass
SL - 10 Sep 2005 18:32 GMT Hi,
I have three classes extending each other :
class a { }
class b extends a { }
class c extends b { }
The class a and b implements a method x(), and the subclass c want to reach a.x(), not the overriding b.x() in the direct superclass. How can I do, and is it a good idea to try doing so ?
I have tried to implement in the class b a method returning a "pointer" (?) to class a, but it does not work :
class b extends a { protected XMLFilter getXMLFilter () { return (XMLFilter) super; } }
but the compiler return :
[javac] C:\home\Corpus\CorpusReader\src\com\LdT\CorpusReader\Pipeline\AbstractBaseFilter.java:96: '.' expected [javac] return (XMLFilter) super; [javac]
Which is the "orthodox" way to face this situation ?
Thanks for your help,
sl
Thomas Fritsch - 10 Sep 2005 20:45 GMT > I have three classes extending each other : > [quoted text clipped - 10 lines] > reach a.x(), not the overriding b.x() in the direct superclass. How > can I do, and is it a good idea to try doing so ? Hi,
Why do you want to call the a.x() method explicitly, and not *the* x() method without actually knowing which x() method you call ? The whole thing behind overriding methods is, that all the x() methods should do very similar things. You should think about a specification of what method x() should do in general and write this as a javadoc-comment into class a. The b.x() methods might do something more special than the generic a.x() method, but nevertheless has to follow the specification given for a.x(). Wanting to call a specific b.x() method may be an indication of an unsolved discrepancy within the class design (sorry, is not meant as an offence!).
(BTW: Please use class names with a capital first letter. That convention is wide-spread, and it makes code easier to understand at first glance.)
 Signature "TFritsch$t-online:de".replace(':','.').replace('$','@')
SL - 11 Sep 2005 10:11 GMT Thank very much for all this answers.
> Why do you want to call the a.x() method explicitly, and not *the* x() > method without actually knowing which x() method you call ? [...]
> The whole thing behind overriding methods is, that all the x() methods > should do very similar things. [...]
> Wanting to call a specific b.x() method may be an indication of an unsolved > discrepancy within the class design (sorry, is not meant as an offence!). You're right. But I'm still wondering if it may be a good solution in a peculiar context... I explain this (perhaps not so) peculiar context
- I am using chained SAX Filter.
- Each filter I design to inherit from org.xml.sax.helpers.XMLFilterImpl.
- The XMLFilterImpl super-class is the only one to hold a reference to the next filter in the pipeline, so that the subclass didn't need to deal with it. When my sub-class want to throw a SAX callback to the next filter, I just need to call the callback on the superclass. For instance, let's say I am in the subclass and I want to throw to the next filter all the start element with local name = "foo" :
public void startElement (String uri, String localName, String qName, Attributes atts) throws SAXException { if (localName.equals("foo") { super.startElement(uri, localName, qName, atts); } }
So the whole pipeline look like :
|----------| |----------| |----------| |XMLFilter |\ |XMLFilter |\ |XMLFilter |\ |----------| \ |----------| \ |----------| \ | \ | \ \ sax stream |----------| \ |----------| \ |----------| \ ------------>|MyFilter1 | -->|MyFilter1 | --> |MyFilter1 | -->etc... |----------| |----------| |----------|
(nice, isn't it ?)
- Moreover, what is greatly useful with this design, is that the subclass need only to implement the callbacks it want to modify -- all the callbacks not implemented in the subclass are received by the XMLFilter superclass and, then, thrown to the next filter in the pipeline. This allows a very economic way of writing filters.
- I want to "reverse" the /default behaviour/ of the superclass. I want that, by default, that the superclass do /not/ throw the callbacks to the next filter, and that the subclass explicitly request for it when it want a callback to be thrown. This is more economic in the kind of situations of much callbacks are to be discarded, but few of them.
So I plan to write an abstract class sitting between the XMLFilterImpl and my subclass :
----------------------------------------
public abstract class *AbstractBaseFilter* extends *XMLFilterImpl* implements [other stuff] {
private boolean *discardCallbacks* = false;
/** * @param discardCallbacks * When a subclass has turn this property to <code>false</code> * it needs to reach directly the XMLFilter on top of this class for * throwing callbacks further in the pipeline. If it sends the events * to its direct superclass (this), they will be silently discarted, * according to the requested behaviour. For reaching this * XMLFilter, it may ask for a reference using {@link * #???}, which return the reference of the superclass. * * <code>true</code> the received callback are thrown to the * super class. * * <code>false</code> (default) the received callback are not * thrown to the super class. */ protected AbstractBaseFilter(boolean discardCallbacks) { this.discardCallbacks = discardCallbacks; }
// Overriding ContentHander callback
public void *startDocument* () throws SAXException { if (!discardCallbacks) { super.startDocument (); } }
}
----------------------------------------
The subclass may turn *discardCallbacks* to true or false according to the wished default behaviour of its superclass.
Now I need, in this subclass, a method allowing the subclass to reach directly the XMLFilterImpl superclass, in ordre when it set *discardCallbacks* to true to throw events in the pipeline. That's why I tried :
protected XMLFilter getXMLFilter () { return (XMLFilter) this; }
I may call, from the subclass, the getContentHandler() of the XMLFilterImpl, for reaching the next filter in the pipeline, but it breaks the principle, in this design, that the subclass must not deal directly with the next filter (if I understand correctly).
Do you think this is poorly designed ?
According to the various answer to my original post, should I rather implement in AbstractBaseFilter new methods throwing /anyway/ the content, like :
----
public void *startDocument* () throws SAXException { if (!discardCallbacks) { super.startDocument (); } }
public void forceStartDocument* () throws SAXException { super.startDocument (); }
----
But I looks poorly designed to, since all methods are duplicated.
I may imagine too that the sublcass directly deal with discardCallbacks, if I declare the variable protected; for instance, when it want to throw something :
discardCallbacks = false; super.startDocument(); discardCallbacks = true;
But it seems to me very error prone to frequently change the value of *discardCallbacks*.
Thanks for your advice.
SL
Thomas Fritsch - 10 Sep 2005 21:16 GMT > I have three classes extending each other : [...]
> The class a and b implements a method x(), and the subclass c want to > reach a.x(), not the overriding b.x() in the direct superclass. How > can I do, and is it a good idea to try doing so ? > > I have tried to implement in the class b a method returning a > "pointer" (?) to class a, but it does not work : What you mean, is probably a reference to an object.
> class b extends a { > protected XMLFilter getXMLFilter () { > return (XMLFilter) super; return super.getXMLFilter(); // would be compilable, but I'm not sure, whether it does what you want. return this; // might also make sense, assumed your class inherits from XMLFilter
> } > }
 Signature "TFritsch$t-online:de".replace(':','.').replace('$','@')
Roedy Green - 10 Sep 2005 23:30 GMT On 10 Sep 2005 19:37:00 +0200, SL <nospam@nospam.com> wrote or quoted
>The class a and b implements a method x(), and the subclass c want to >reach a.x(), not the overriding b.x() in the direct superclass. How >can I do, and is it a good idea to try doing so ? then either a or b must preserve that functionality for you under a different name. You have no ability to dig deeper than one level on your own.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Roedy Green - 10 Sep 2005 23:31 GMT On 10 Sep 2005 19:37:00 +0200, SL <nospam@nospam.com> wrote or quoted
>The class a and b implements a method x(), It is very confusing when you ignore naming conventions. See http://mindprod.com/jgloss/namingconventions.html
Please rephrase that as : The classes A and B implement a method x(),
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Bjorn Abelli - 11 Sep 2005 08:59 GMT "SL" wrote...
> I have three classes extending each other : > [quoted text clipped - 10 lines] > reach a.x(), not the overriding b.x() in the direct superclass. How > can I do, and is it a good idea to try doing so ? [snip]
> Which is the "orthodox" way to face this situation ? The "orthodox" way is to not do it... ;-)
Any given subclass is a specialization of its immediate superclass, and hence you are confined to specialize only the behaviour inherited from that superclass, not further up in the hierarchy.
If you want an "un-orthodox" way to solve it, you could use a reversed "Template Method"-pattern, something like this:
class a { public void x() { ax(); } final protected void ax() { } }
class b extends a {
public void x() { bx(); } protected void bx() {} }
class c extends b { public void x() { ax(); } }
In the "Template Method"-pattern, it's the other way around, that the inherited "x" calls methods that are supposed to be overridden. In this reversed variant, the called methods are left intact, so they are available throughout the hierarchy. It's possible that this pattern exists under another name.
It's a bit clumsy, and there are probably better ways of doing this, but I have used it on occasion...
// Bjorn A
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|