Suppose I have the following situation:
public abstract class Vehicle {
public void turnOn() { ... }
}
public interface Flier {
public void fly();
}
You could rearrange your classes and interfaces like this:
public interface IVehicle {
public void turnOn();
}
public abstract class Vehicle implements IVehicle {
public void turnOn() { ... }
}
public interface Flier extends IVehicle {
public void fly();
}
This way all implementations of Flier
are guaranteed to implement the protocol of a vehicle, namely IVehicle
.
It's a strange requirement, but you can accomplish something of the sort with Generics:
<T extends MyInterface & MyAbstractClass>
This question shows that you haven't grasped the essence of interface
and class
. Forgetting the concrete Java syntax right now, all you need to understand first is that: interface is a set of protocol, which should be implementation-agnostic. It makes no sense to let an interface extend a class(which is implementation-oriented).
Back to your concrete question, if you want to guarantee that a Flier
is always a kind of Vehicle
, just change the latter to an interface
and let former extends it(It does make sense to extend one protocol from the other protocol). After that, you may create any class(abstract or concrete) that implements Vehicle
or Flier
.
Java interfaces cannot extend classes, which makes sense since classes contain implementation details that cannot be specified within an interface..
The proper way to deal with this problem is to separate interface from implementation completely by turning Vehicle
into an interface as well. The Car
e.t.c. can extend the Vehicle
interface to force the programmer to implement the corresponding methods. If you want to share code among all Vehicle
instances, then you can use a (possibly abstract) class as a parent for any classes that need to implement that interface.
If you have control on the Vehicle
classes just extract Vehicle
as an interface and then provide a base implementation.
If you have no control over Vehicle
class, for example because it is part of a framework you are using or a third party library, it's not possible to do in Java.
The closest thing you can do is using Generics multiple wildcards notation.
<T extends Vehicle & Car>
But you can't really apply it directly to Car unless you do something like this:
public interface Car<T extends Vehicle & Car>() {
T self();
}
Which is bot weird and do not enforce the self method to actually return self, it's just a strong hint/suggestion.
You would implement a Car
like this:
public class CitroenC3 extends Vehicle implements Car<CitroenC3> {
@Override
public CitroenC3 self() {
return this;
}
}
one can use a Car<?>
like this:
Car<?> car = obtainCarInSomeWay();
Vehicle v = car.self();
Car c = car.self();
they should be both valid syntax.
What the compiler enforce here is that what you specify in Car<WHICH>
as WHICH must both extend Vehicle
and implement Car
. And by adding self()
you are saying to the programmer that the T
object is supposed to be the object itself, thus forcing the wildcard instance to match the class if he want to be compliant with the specification.
in Java 8 you can even define a default implementation for the self method.
I also wish there was a better way to handle something like this.
Now: Whenever you like to implement from "Flier" you must extends from Vehicle ! (because only Vehicle can implement implementMe).
This is tricky but works great.