"If you want to have two classes extend the same abstract class, you have to place the the abstract class high up in the type hierarchy where it subclasses an ancestor of both the classes. Unfortunately, this causes great collateral damage to the type hierarchy, forcing all descendants of the common ancestor to extend the new abstract class whether or not it is appropriate for them to do so."
But , I dont think it would force all descendants of the common ancestor to extend the new abstract class. The descendants can continue to extend the ancestor class itself right? Please help me understand this.
Since Java is object oriented, let us consider it in object oriented way.
Consider this example
We have Car and Bike.
Both vehicles runs on Petrol. So I can make an abstract class PetrolVehicle and let Car and Bike extends it.
Now code becomes
So far it is fine .. there is no problem with code.
Problem may arise as soon as you start adding subclasses to Car. Now Car can run on Petrol, Diesel, CNG etc.
Let us say we want to extend Car class to make one subclass - CNGCar
Now the problem is CNGCar has accessor - PetrolVehicle which contradicts.... That's what author means - "Unfortunately, this causes great collateral damage to the type hierarchy, forcing all descendants of the common ancestor to extend the new abstract class whether or not it is appropriate for them to do so."
Hope I have made myelf clear.
Having PetrolVehicle is a good example of what one should probably not have in an object hierarchy - it supposes the single most important thing about different vehicles is the type fuel it uses. While that may be true for some specialized applications, more generally we would be in trouble if later it emerges that differentiating based on the number of wheels is much more important? We'd have to recreate the object model fundamentally.
So since the fuel type is only one aspect of a vehicle, it's better to make that an interface instead of its own class. That way the object model can even accommodate if a car is available in both petrol and natural gas variants (by implementing both interfaces).
Agreed with Ulf .. Having PetrolVechicle is not good design .. I just created this whole [ supposedly bad design] scenario to explain what is written in Effective Java book...
So since the fuel type is only one aspect of a vehicle, it's better to make that an interface instead of its own class. That way the object model can even accommodate if a car is available in both petrol and natural gas variants (by implementing both interfaces).
I think we can even define Fuel Type as Enum and have Petrol Natural Gas etc inside it. And class can have Enum array type instance variable to store Fuel Type
Abhay Agarwal wrote:I think we can even define Fuel Type as Enum and have Petrol Natural Gas etc inside it. And class can have Enum array type instance variable to store Fuel Type
Good point. That works as long as each car has just one single fuel type. So it would be OK if by "car" we refer to a specific instance of a car, like "your car". It wouldn't work if by "car" we mean a model, like "BMW X 1", because that can have either a petrol or a diesel engine. So it depends on what we'll be using the object model for.