Suppose I have the following four classess, out of which two are abstract and two are concrete: Abstract1
, Concrete1
, Abstract2
, Concrete2
.
Concrete1
extends Abstract1
and Concrete2
extends Abstract2
.
Suppose I have the following four classess, out of which two are abstract and two are concrete: AbstractProp
, ConcreteProp
, AbstractClass
, ConcreteClass
.
ConcreteProp
extends AbstractProp
and ConcreteClass
extends AbstractClass
.
The code for AbstractClass
would look like the following:
public abstract class AbstractClass {
protected AbstractProp someProperty;
public abstract void setProperty(AbstractProp someProperty);
}
When implementing ConcreteClass
, I want to be able to do something like this (keep in mind that AbstractProp
extends `ConcreteProp):
public class ConcreteClass extends AbstractClass {
@Override
public void setProperty(ConcreteProp someProperty) {
this.someProperty = someProperty;
}
}
But this last bit of code isn't valid because the classes of the parameters (AbstractProp
and ConcreteProp
) in setProperty()
differ, making the @Override
annotation invalid. Is there a way I can accomplish what I'm trying to do here, perhaps using generics and/or wildcards?
NOTE: I'm aware that this type of naming is bad practice and the code is oversimplistic, I'm not actually using it and this is just an example to keep the question as simple as possible.
If you introduce generics on the AbstractClass
you can achieve what you are requesting.
public abstract class AbstractClass<T extends AbstractProp> {
protected T someProperty;
public void setProperty(T someProperty) {
this.someProperty = someProperty;
}
}
And then specify that you want ConcreteProp
to be the type you want in your ConcreteClass
.
public class ConcreteClass extends AbstractClass<ConcreteProp> {
@Override
public void setProperty(final ConcreteProp someProperty) {
this.someProperty = someProperty;
}
}