Francesc Lordan
Francesc Lordan

Reputation: 529

Java - Is it possible to extend all the subclasses of a class with a single class?

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

Answers (8)

DAB
DAB

Reputation: 1873

No, it's not like C++. Multiple inheritance is not possible in Java. However you can implement multiple interfaces.

Upvotes: 1

zerobandwidth
zerobandwidth

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

Gavin
Gavin

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

Bhushan
Bhushan

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

callOfCode
callOfCode

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

ernest_k
ernest_k

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

Robert Br&#228;utigam
Robert Br&#228;utigam

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

Solorad
Solorad

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

Related Questions