Java Forum / General / April 2006
Overwrite Default Constructor ?
Philipp Leitner - 17 Apr 2006 18:09 GMT hi all,
this may be a silly question, but is there actually any way to _overwrite_ a constructor of a superclass in Java?
I have the following inheritance structure:
"ProfileAdmin" inherits from "ProfileSearcher"
both classes are almost identical, the main difference is that the constructor of ProfileSearcher throws an exception in certain circumstances, while ProfileAdmin should try to repair the problem in these cases (with the reason that ProfileSearcher should be used on thin clients, which are not capable of the cpu-heavy repair actions).
My first idea would have been to just overwrite the constructor of ProfileSearcher, but I quickly discovered that javac inserts an implicit "super()" at the beginning of the subclasses' constructor (I really had no clue about that in advance ...) :-(
Any tips on how to solve this issue in a clean way?
thx in advance, Philipp
 Signature Philipp Wolfgang Leitner, Bakk.rer.soc.oec. 0225511 Vienna University of Technology
"Ask five economists and you'll get five different explanations (six if one went to Harvard). -- Edgar R. Fiedler"
Oliver Wong - 17 Apr 2006 18:44 GMT > hi all, > > this may be a silly question, but is there actually any way to _overwrite_ > a constructor of a superclass in Java? Not to my knowledge.
> I have the following inheritance structure: > [quoted text clipped - 5 lines] > these cases (with the reason that ProfileSearcher should be used on thin > clients, which are not capable of the cpu-heavy repair actions). You could have ProfileAdmin catch the exception. But are you sure ProfileAdmin should be a subclass of ProfileSearcher?
> My first idea would have been to just overwrite the constructor of > ProfileSearcher, but I quickly discovered that javac inserts an implicit > "super()" at the beginning of the subclasses' constructor (I really had no > clue about that in advance ...) :-( > > Any tips on how to solve this issue in a clean way? Perhaps you can add a protected constructor in ProfileSearcher which "does nothing" (or at least, doesn't throw exceptions), which your subclasses (e.g. ProfileAdmin) could use.
- Oliver
Thomas Hawtin - 17 Apr 2006 18:16 GMT >> "ProfileAdmin" inherits from "ProfileSearcher" >> [quoted text clipped - 6 lines] > You could have ProfileAdmin catch the exception. But are you sure > ProfileAdmin should be a subclass of ProfileSearcher? Tricky to catch an exception thrown from a super constructor call...
> Perhaps you can add a protected constructor in ProfileSearcher which > "does nothing" (or at least, doesn't throw exceptions), which your > subclasses (e.g. ProfileAdmin) could use. Yup. I'd go further to suggest making non-leaf classes abstract.
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Oliver Wong - 17 Apr 2006 20:42 GMT >>> "ProfileAdmin" inherits from "ProfileSearcher" >>> [quoted text clipped - 8 lines] > > Tricky to catch an exception thrown from a super constructor call... I was aware of the rule that "super()" has to be the first statement, but I wasn't aware that a "try-catch" block "counts" as a statement. So I tried the obvious:
<code> public class Foo { public Foo() { try { super(); } catch (Throwable t) {
} } } </code>
and indeed it doesn't compile.
- Oliver
Philipp Leitner - 17 Apr 2006 20:45 GMT well, I tried the same before myself ... and yes, this doesn't compile ...
for now I went with the idea with a "dummy" protected constructor, but I have to say I don't like the solution much. Perhaps I am really going to change the inheritance into an aggregation of some kind.
/philipp
Oliver Wong schrieb:
>>>> "ProfileAdmin" inherits from "ProfileSearcher" >>>> [quoted text clipped - 29 lines] > > - Oliver Andrew McDonagh - 17 Apr 2006 22:26 GMT > well, I tried the same before myself ... and yes, this doesn't compile ... > > for now I went with the idea with a "dummy" protected constructor, but I > have to say I don't like the solution much. Perhaps I am really going to > change the inheritance into an aggregation of some kind. If these classes really do need to be bound in by Inheritance rather than delegation, then the best approach for your design problem is to not use public constructors at all.
Instead, use public factory methods on those classes, protected constructors and move all logic from constructors into init methods. This way, you can get full control over what happens.
class Base { protected Base() { }
protected init( if (someCondition) throw new RuntimeException(); }
public static Base createBase() { Base base = new Base(); base.init(); return base; } }
class Derived extends Base {
protected Derived() { }
protected init() { try { super.init(); catch(RuntimeException re) { system.out.println(re); } }
public static Derived createDerived() { Derived derived = new Derived(); derived.init(); return derived; }
}
Roedy Green - 17 Apr 2006 21:22 GMT >but I wasn't aware that a "try-catch" block "counts" as a statement. So I >tried the obvious: To avoid the violating the super comes first rule, you need something like this:
super( doeseverythingbuteat( parm1 ) );
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Philipp Leitner - 17 Apr 2006 21:34 GMT > To avoid the violating the super comes first rule, you need something > like this: > > super( doeseverythingbuteat( parm1 ) ); sorry, I don't get that ;-) How would something like that help me catch the exception that super() throws?
/philipp
Patricia Shanahan - 17 Apr 2006 21:39 GMT >> To avoid the violating the super comes first rule, you need something >> like this: [quoted text clipped - 5 lines] > > /philipp It doesn't, but it may help you prevent the exception. In some cases you could check for the condition that causes the exception, and prevent it from happening. It is most useful for things like incorrect parameters.
Patricia
Philipp Leitner - 17 Apr 2006 21:52 GMT > It doesn't, but it may help you prevent the exception. In some cases you > could check for the condition that causes the exception, and prevent it > from happening. It is most useful for things like incorrect parameters. ok, now I get what you meant; unfortunately this would be quite strange (if not impossible) to do in my case since I heavily depend on member variables.
/philipp
Patricia Shanahan - 17 Apr 2006 22:07 GMT >> It doesn't, but it may help you prevent the exception. In some cases you >> could check for the condition that causes the exception, and prevent it [quoted text clipped - 5 lines] > > /philipp Here's another approach. Make the ProfileAdmin constructor private, have it throw the exception, and supply a static factory method.
The factory method could wrap the attempt to create the object in a try-catch, and do whatever fix-up it likes on catching the exception. Make sure the exception carries enough data for the constructor caller to know what fix-up is needed.
Patricia
Andrew McDonagh - 17 Apr 2006 22:29 GMT >> It doesn't, but it may help you prevent the exception. In some cases you >> could check for the condition that causes the exception, and prevent it [quoted text clipped - 5 lines] > > /philipp Its also not a great design choice, because now the derived class would have knowledge of what is good or bad data from its base class.
You'd never want coupling that is this tight.
Roedy Green - 17 Apr 2006 21:51 GMT On Mon, 17 Apr 2006 22:34:31 +0200, Philipp Leitner <philipp.leitner@gmx.at> wrote, quoted or indirectly quoted someone who said :
>> super( doeseverythingbuteat( parm1 ) ); > >sorry, I don't get that ;-) How would something like that help me catch >the exception that super() throws? It wouldn't, but you could do a test to detect the condition that would upset super and handle it.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Chris Uppal - 18 Apr 2006 10:15 GMT > I was aware of the rule that "super()" has to be the first statement, > but I wasn't aware that a "try-catch" block "counts" as a statement. The idea is that the system doesn't "allow" you to see an object in an incompletely constructed state[*]. If the super-class's constructor has, in effect, said "No you can't create this object", then Java and the JVM won't let a subclass say "Bugger that! I'm going to create it /anyway/".
([*] I agree that the guards against this are a little leaky...)
-- chris
Chris Smith - 18 Apr 2006 17:45 GMT > > I was aware of the rule that "super()" has to be the first statement, > > but I wasn't aware that a "try-catch" block "counts" as a statement. [quoted text clipped - 3 lines] > effect, said "No you can't create this object", then Java and the JVM won't let > a subclass say "Bugger that! I'm going to create it /anyway/". Yep, and the problem of course is that a try/catch block is not used merely to ignore exceptions, but also to wrap them... which may be a quite sensible thing to want to do.
In this case, though, it appears there's something wrong with the inheritance structure.
 Signature www.designacourse.com The Easiest Way To Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer MindIQ Corporation
James Of Tucson - 17 Apr 2006 21:58 GMT >Any tips on how to solve this issue in a clean way? Investigate the "Factory" design pattern.
Tony Morris - 18 Apr 2006 04:43 GMT > hi all, > [quoted text clipped - 20 lines] > thx in advance, > Philipp You're referring to, I assume, a no-argument constructor. This is not the same thing as a default constructor, albeit common misconception.
You're also experiencing a consequence of the inherent excess requirement (and subsequent requirment defect) that is implied by the semantics of Java (and all known OO languages) constructors. Live with it, fix it, or workaround it.
ContractualJ (http://contractualj.com/): All constructors are declared private, and throw java.lang.UnsupportedOperationException, unless they are implicit constructors of anonymous classes. Exposing construction details (as Java constructor semantics implies) is not permitted.
 Signature Tony Morris http://tmorris.net/
Jeroen V. - 18 Apr 2006 18:27 GMT You can avoid executing the code in the superconstructor by wrapping the superconstructor code with:
if(this.getClass().getName().equals(com.xxx.yyy.ProfileSearcher){ //constructor code }
Jeroen V. - 18 Apr 2006 18:29 GMT > You can avoid executing the code in the superconstructor by wrapping the > superconstructor code with: > > if(this.getClass().getName().equals(com.xxx.yyy.ProfileSearcher){ > //constructor code > } should be:
if(this.getClass().getName().equals("xxx.yyy.ProfileSearcher"){ //constructor code }
James McGill - 18 Apr 2006 19:03 GMT > > You can avoid executing the code in the superconstructor by wrapping the > > superconstructor code with: [quoted text clipped - 8 lines] > //constructor code > } How is there a "this" if the superconstructor hasn't been called?
Oliver Wong - 18 Apr 2006 19:25 GMT >> > You can avoid executing the code in the superconstructor by wrapping >> > the [quoted text clipped - 11 lines] > > How is there a "this" if the superconstructor hasn't been called? I think what Jeroen is saying to put the above code in the superconstructor so that when it is called from within the subclasses, the condition will return false, and so the constructor code won't get executed, and thus no exception will be thrown.
It's a possible solution, but I think the protected do-nothing constructor paired along with the factory methods is a cleaner one.
- Oliver
James McGill - 18 Apr 2006 21:09 GMT > It's a possible solution, but I think the protected do-nothing > constructor paired along with the factory methods is a cleaner one. Yeah, I was going to ask what's wrong with Factory that makes such "solutions" seem attactive to people. I suspect that's just because there are people who haven't read GoF or its derivatives, and who are struggling to find an approach to a common problem on their own.
Jeroen V. - 18 Apr 2006 21:35 GMT > Yeah, I was going to ask what's wrong with Factory that makes such > "solutions" seem attactive to people. I suspect that's just because > there are people who haven't read GoF or its derivatives, and who are > struggling to find an approach to a common problem on their own. I'm impressed you've read GoF.
I'm wondering why you're substituting my name with "there are people who". I suspect there are people who think they have a superior mind because they've read some book. Still impressed.
I didn't say that anything was wrong with the factory design pattern. I didn't say that my solution was more or less attractive, neither did I say my solution was attractive at all.
From your post I derive that alternatives to a solution may not be considered. Why is that? (don't answer this one) Instead of insulting me of doing useless thinking, you'd better give me a reason why my solution is not a solution (or how should I interpret your quotes?)
I will tell you why my solution is a solution: 1. I'm allowed to define in the contract of the superclass that all childclasses are responsible themselves for initializing the instance fields. 2. Childclasses must obey the contract
Yours sincerely,
Jeroen
Andrew McDonagh - 18 Apr 2006 23:23 GMT snipped
> I will tell you why my solution is a solution:
> 1. I'm allowed to define in the contract of the superclass that all > childclasses are responsible themselves for initializing the instance > fields. Is that the instance variables of the base class?
if so - How do the derived classes do this without using the base class constructor?
if not - then aren't derived classes usually responsible for initializing their own instance fields?
> 2. Childclasses must obey the contract I didn't see anything from the code snipped that would 'force' derived classes from doing so.
I did see the potential for a 'convention' that derived class designers should follow.
> Yours sincerely, > > Jeroen Cheers
Andrew
Jeroen V. - 19 Apr 2006 08:50 GMT > Is that the instance variables of the base class? yes
> if so - How do the derived classes do this without using the base class > constructor? I mean initializing to non-default values. The super constructor is called anyway, just not the if-then part. Public or protected setters in the baseclass can be used for this.
>> 2. Childclasses must obey the contract > > I didn't see anything from the code snipped that would 'force' derived > classes from doing so. I didn't say that. I did say that in the contract between the baseclass and its derived classes, there is a clause saying that the derived class is responsible for initing the superclass instance fields. This must not be reflected in code.
> I did see the potential for a 'convention' that derived class designers > should follow. That's what I mean.
>> Yours sincerely, >> [quoted text clipped - 3 lines] > > Andrew James McGill - 19 Apr 2006 02:27 GMT You seem to have taken my comments very personally.
I don't know of a single undergrad CS curriculum that does not have at least one course on object design using patterns. I assume everyone is familiar with the basic design patterns, just as I assume they are familiar with the relative complexity among various discrete structures.
> From your post I derive that alternatives to a solution may not be > considered. Why is that? (don't answer this one) You're taking my comments as a personal attack on your coding style. I'm fully aware there are many ways to solve a problem. But the one on the table really looks like it's abusing the language, and trying to make it do something that it's more or less trying to prevent you from doing.
> Instead of insulting me of doing useless thinking Whoa there. Who is insulting whom?
> , you'd better give me > a reason why my solution is not a solution (or how should I interpret > your quotes?)
> I will tell you why my solution is a solution: > 1. I'm allowed to define in the contract of the superclass that all > childclasses are responsible themselves for initializing the instance > fields. > 2. Childclasses must obey the contract Fair enough. But you're doing something that I could never make myself do: Designing an Exception handler into normal behavior.
Jeroen V. - 18 Apr 2006 21:10 GMT > I think what Jeroen is saying to put the above code in the > superconstructor so that when it is called from within the subclasses, > the condition will return false, and so the constructor code won't get > executed, and thus no exception will be thrown. That's what I mean :-)
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 ...
|
|
|