Reputation: 1255
public abstract class AbstractClass
{
public abstract void AbstractClassMethod();
}
public class DerivedClass extends AbstractClass {
@Override
public void AbstractClassMethod() {
// TODO Auto-generated method stub
}
}
public interface InterfaceObject
{
public void InterfaceObjectMethod(AbstractClass oAbstractClass);
}
public class TestAbstractParam implements InterfaceObject {
@Override
public void InterfaceObjectMethod(AbstractClass oAbstractClass) {
// TODO Auto-generated method stub
}
}
public class TestDerivedParam implements InterfaceObject {
@Override
public void InterfaceObjectMethod(DerivedClass oDerivedClass) {
// TODO Auto-generated method stub
}
}
I am getting error while compiling TestDerivedParam class. Can anyone please explain the reason behind this? More specifically, the question is why a method cant accept a child type parameter which is expecting a base type? Thank you!
Upvotes: 0
Views: 2317
Reputation: 51030
In TestDerivedParam
the method
public void InterfaceObjectMethod(DerivedClass oDerivedClass) {
is not same as
public void InterfaceObjectMethod(AbstractClass oAbstractClass);
in InterfaceObject
.
You are using @Override
annotation but are not using the same method signature.
More specifically, the question is why a method cant accept a child type parameter which is expecting a base type?
See the example below:
public class Fruit { }
public class Apple extends Fruit { }
public class Banana extends Fruit { }
Both Apple
and Banana
are Fruit
but Apple
is not Banana
and Banana
is not Apple
. So, you can't really give Banana
to somebody who is expecting Apple
, but it would be valid to give either a Banana
or an Apple
to somebody who is just expecting a Fruit
.
So,
public void method(Fruit fruit) {
does not have same signature as
public void method(Apple apple) {
because, if it was then that would mean the following has the same signature as the above
public void method(Banana banana) {
And the signature has to match while overriding (implementing) a method.
Upvotes: 1
Reputation: 78579
You are changing the signature of the method, as such, Java can only assume your intention is to "overload" an existing method with the same name and different parameters.
You may alternatively use a bridge method:
@Override
public void InterfaceObjectMethod(AbstractClass oDerivedClass) {
// TODO Auto-generated method stub
}
public void InterfaceObjectMethod(DerivedClass oDerivedClass) {
InterfaceObjectMethod((AbstractClass)oDerivedClass);
}
This second method would be a bridge method, whose responsibility is simply forwarding your request to the actual inherited method. As you can see the bridge method is an overloading, not an overriding.
Another option is to use generics.
interface InterfaceObject<T extends AbstractClass>
{
public void InterfaceObjectMethod(T oAbstractClass);
}
class TestAbstractParam implements InterfaceObject<AbstractClass> {
@Override
public void InterfaceObjectMethod(AbstractClass oAbstractClass) {
// TODO Auto-generated method stub
}
}
class TestDerivedParam implements InterfaceObject<DerivedClass> {
@Override
public void InterfaceObjectMethod(DerivedClass oDerivedClass) {
// TODO Auto-generated method stub
}
}
Ultimately, the generics version does exactly the same as the first option, that is, a bridge method is synthetically generated by the compiler. If you decompile your classes you would notice it does exactly that.
Upvotes: 0