Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jump over parent constructor to call grandparent's

Tags:

java

oop

The problem is this: I have an abstract class that does some work in its constructor, and a set of child classes that implement the abstract class:

class AbstractClass {
     AbstractClass(){ /* useful implementation */ }
}

class ConcreteClass1 extends AbstractClass {
     ConcreteClass1(){ super(); /* useful implementation */ }
}

Then, the concrete classes need to be customized and one solution is to extend the concrete classes:

class CustomizedClass1 extends ConcreteClass1 {
    CustomizedCLass1(){ super(); /* useful implementation */ }
}

BUT the problem is that the customized classes need only to call the abstract class's constructor and not the concrete class's constructor.

How do you achieve this? Suggestions to change the class's relationships are valid.

EDIT: The concrete example is that ConcreteClass1 and CustomizedClass1 have different sets of data (ConcreteData1 and CustomizedData1), and it is retrieved from the database in the class's constructor. The problem is that creating an instance of CustomizedClass1 will retrieve both data entities.

I am aware that using simple inheritance it's probably not the best thing to do, that's why I pointed out that suggestions to change the class's relationships are valid.

like image 549
German Avatar asked Dec 10 '09 04:12

German


4 Answers

Is CustomizedData1 a subclass of ConcreteData1? If so, then I would suggest having a (possibly protected) constructor for ConcreteClass1 that takes in a ConcreteData1 to use instead of fetching its own during initialization. This way, CustomizedClass1 can fetch its CustomizedData1 and pass it to its call to super. Unfortunately this may be tricky or fairly impossible if you can't fetch the data prior to some internal init.


class ConcreteClass1 extends AbstractClass {
     ConcreteClass1(){
          this(...fetch data as before...);
     }
     ConcreteClass1(ConcreteData1 data){
          myData = data;
          ...
     }
}
class CustomizedClass1 extends ConcreteClass1 {
     CustomizedCLass1(){
          super(new CustomizedData1(...));
          ... 
     }
}

But then CustomizedClass1 probably needs a reference to the data as a CustomizedData1 not merely a ConcreteData1. It could just typecast its inherited ConcreteData1 all the time, but that seems yucky. But if it stores its own reference to the data, then there is a need to keep the references in sync if they're not final.

like image 100
user401321 Avatar answered Oct 05 '22 23:10

user401321


You cannot do this in Java. I frequently have students who want to do this, but I have never seen a case where it is really what they wanted to do.

Can you give a concrete example of what it is you want to do and why (your description is too vague) and I am sure a solution can be achieved :-)

Edit:

For a real world example of why you do not want to do this (normally) would be a hierarchy like:

Animal (constructor makes the eyes)
  |
Mammal (constructor makes the lungs)
  |
Human (constructor sets the language)

If the Human constructor could skip over the Mammal constructor then you would wind up with a Human who has no lungs... not very useful.

like image 22
TofuBeer Avatar answered Nov 19 '22 14:11

TofuBeer


Easy (but why?):

class AbstractClass {
   AbstractClass(){ /* useful implementation */ }
}

class ConcreteClass1 extends AbstractClass {
     ConcreteClass1(){ super(); /* useful implementation */ }
     ConcreteClass1(boolean skip){ super(); }
}
class CustomizedClass1 extends ConcreteClass1 {
     CustomizedCLass1(){ super(true); /* useful implementation */ }
}
like image 11
MattMcKnight Avatar answered Nov 19 '22 12:11

MattMcKnight


Any instance of CustomizedClass1 is also an instance of ConcreteClass1, by definition, so it must be constructed as a valid ConcreteClass1 instance before the CustomizedClass1 constructor can run. Otherwise, what would happen if you called ConcreteClass1 methods on it? They'd be trying to operate on variables that haven't been initialized yet.

If you think you need to do this, chances are your design needs re-thinking. If you only want some of the functionality from ConcreteClass1, for example, that functionality could be factored out into a superclass of ConcreteClass1, and CustomizedClass1 could extend that to get just the functionality that it needs.

Please provide more information about the relationship between these classes.

like image 8
Wyzard Avatar answered Nov 19 '22 13:11

Wyzard