Reputation: 529
Java - Is it possible to extend all the subclasses of a class with a single class?
Let's explain it with an example, the actual code is quite more complex. I have an Animal class with its own class hierarchy. Let's say that it has two subclasses: Testarrosa and Viper.
public class Car {
public abstract String getManufacturer();
}
public class Testarossa extends Car{
public String getManufacturer(){
return "Ferrari";
}
}
public class Viper extends Car{
public String getManufacturer(){
return "Dodge";
}
}
I want to extend all the Car subclasses with a RegisteredCar subclass.
public class RegisteredCar extends Car {
private String plateNumber;
public RegisteredCar (String plateNumber){
this.plateNumber=plateNumber;
}
public String getPlateNumber() {
return plateNumber;
}
}
At some point, I should be able to create a new RegisteredCar of a specific subclass. Something like
RegisteredCar c = new RegisteredCar<Viper>("B-3956-AC");
And call the c.getManufacturer() to obtain "Dodge" and c.getPlateNumber() to obtain B-3956-AC. Obviously, I should still be able to create a Car c = new Viper();
That is an example. Having an attribute in Car with null value if not registered is not enough for what I need.
Upvotes: 6
Views: 1607
Reputation: 1873
No, it's not like C++. Multiple inheritance is not possible in Java. However you can implement multiple interfaces.
Upvotes: 1
Reputation: 1303
Is there a reason, in the real classes, that you couldn't simply add the new feature to the existing base class?
public abstract class Car
{
public abstract String getManufacturer() ;
protected String plate_number = null ;
public String getPlateNumber()
{ return this.plate_number ; }
public boolean isRegistered()
{ return ( this.plate_number != null ) ; }
}
Upvotes: 0
Reputation: 1767
As others have said, no thats not really possible and your example could be solved by changing your model
As an alternative to inheritance you could use another class to wrap a Car
instance.
I would make Car
an interface (though having RegisteredCar
extend Car
should work too) and then attempt something like the following pseudo code:
class RegisteredCar<T extends Car> implements Car {
private final T car
RegisteredCar(T car) {
this.car = car;
}
... methods for RegisteredCar
... methods from Car delegating to `this.car`
}
Please excuse the somewhat bad code, I don't have an IDE open, and I always mess up generics without an IDE to hand.
Another possible solution is to use AOP, though I don't know how in fashion that is these days as but what you are describing could be a cross cutting concern.
A final alternative might be to use a language that allows for Extensions, Traits, Protocol or some other type of 'mix in'
Upvotes: 4
Reputation: 567
With Generic class approach as described in other answer, you will not be able to use RegisteredCar
where your require to pass Car
object. e.g. suppose you need to generate some invoice.
Invoice getInvoice(Car c);
In this method you cannot use RegisteredCar
as it is not of Type Car. All you API which require Car are not applicable to RegisteredCar
. In some cases you may need Plate Number as well as Car, There you may need to keep mapping of Plate Number and Cars. I would suggest following approach based on Decorate Pattern and delegate all Car calls to passed car object
public class RegisteredCar extends Car{
public RegisteredCar(Car c, String plateNumber){
}
@Override
String getColor(){
c.getColor();
}
}
Upvotes: 1
Reputation: 1026
You should avoid inheritance as much as possible. Use abstractions (interfaces) to make your code elegant and maintainable. Just google why extends is evil.
public interface Car{
String getManufacturer();
}
public interface Registerable{
boolean isRegistered();
void register(String plateNumber);
void getPlateNumber();
}
public class Viper implements Car, Registerable
{
//all methods
}
Upvotes: 2
Reputation: 45339
You cannot achieve that with inheritance. Your best option is making the RegisteredCar type generic, then having a generic instance variable that holds the intended type car:
public class RegisteredCar<T extends Car> {
private String plateNumber;
private T car;
public T getCar() {
return this.car;
}
public T setCar(T car) {
this.car = car;
}
public RegisteredCar (String plateNumber){
this.plateNumber=plateNumber;
}
public String getPlateNumber() {
return plateNumber;
}
}
With this, you will be able to pass into RegisteredCar an object of any type that's a subclass of Car.
As you can notice, I have removed the extends Car
part of this class, as it doesn't need to be a subclass of car itself.
Upvotes: 0
Reputation: 7744
In short, no that is not possible. You have to unfortunately modify your object model.
For example, what about having a Registration
class this way:
public interface Registration<C extends Car> {
C getCar();
String getPlateNumber();
}
This way you can extract the information relating to registration in a single class, while maintaining your Car
models.
You can then do helper methods like:
Registration<Viper> registeredViper = createRegistration(new Viper(), "B-3956-AC");
Upvotes: 10
Reputation: 914
In java it is prohibited to extends more than 1 class. You could build chain from classes to extends, for example. To solve the problem of mutiple inheritance in Java → interface is used
Upvotes: 2