(This is a follow up to this question, which itself was a follow up to this question.)
I have the following interfaces/classes (skeleton code below)
interface Copyable<C extends Copyable<C>> {
interface Validator<V extends Validator<V>> extends Copyable<V> {
interface ValidateValue<O> extends Validator<ValidateValue<O>> {
abstract class AbstractValidator<V extends AbstractValidator<V>> implements Validator<V> {
class VVNull<O> extends AbstractValidator<VVNull<O>> implements ValidateValue<O> {
This used to work just grand when Copyable
was implemented without the <C extends Copyable<C>>
but, as the two previous questions make clear to me, Copyable
really needs those generics.
Unfortunately, now I can't compile VVNull
.
C:\java_code\CopyableCProblem.java:23: error: Validator cannot be inherited with different arguments: <ValidateValue<O>> and <VVNull<O>>
This is line 23 in the below source-code:
class VVNull<O> extends AbstractValidator<VVNull<O>> implements ValidateValue<O> {
VVNull<O>
is a ValidateValue<O>
. It passes itself up as a generic-parameter for goodness-sakes, and it implements ValidateValue<O>
. The inheritance is completely linear--there's no "diamond" inheritance or anything, it's Copyable<--Validator<--ValidateValue<--VVNull
.
I realize--or actually, I should say I think--that self-generics will work, that is, if you make every class self-genericized, such as
VVNull<O,V extends VVNull<O,V>>
but I am desperate to find another solution. Self-referential generics are a complete mess when you get down to sub-classes that need their own additional generics. That's why I only self-genericize through Validator
, because it's the least-likely candidate to be directly used. ValidateValue
and VVNull
are frequently and directly used. I really really hope that there are other possibilites.
Comparable works just fine without requiring self-generics in all its implementing classes, so how can I make this work for Copyable
?
Thank you for any advice.
public class CopyableCProblem {
}
interface Copyable<C extends Copyable<C>> {
C getObjectCopy();
}
interface Validator<V extends Validator<V>> extends Copyable<V> {
}
interface ValidateValue<O> extends Validator<ValidateValue<O>> {
@Override
ValidateValue<O> getObjectCopy();
boolean isValid(O o_o);
}
abstract class AbstractValidator<V extends AbstractValidator<V>> implements Validator<V> {
}
class VVNull<O> extends AbstractValidator<VVNull<O>> implements ValidateValue<O> {
@Override
public VVNull<O> getObjectCopy() {
return this;
}
public boolean isValid(O o_o) {
return (o_o != null);
}
}