根据(§8.4.8.1),如果 的签名是的签名的子签名( §8.4.2),则实例方法将m1
覆盖另一个实例方法m2
m1
m2
。
换句话说,重写方法签名应该与重写方法签名或重写方法签名的擦除(第 4.6 节)相同。
因此,被覆盖的方法参数不能用覆盖方法中不太具体的类型的参数替换。你可以在这里阅读为什么会这样。
在您的情况下,ObjectSet#getValue
签名与ColumnSet#getValue
签名及其擦除签名(Object getValue(Column column)
)不同。也是如此ParameterSet#getValue
。
正如@samabcde所指出的,如果基本方法声明如下:
<V, I extends Column & Input<V>> V getValue(I column);
<V, I extends Parameter & Input<V>> V getValue(I value);
您可以按如下方式实现它们:
@Override
public <V, I extends Column & Input<V>> V getValue(I value) {
return doGetValue(value);
}
@Override
public <V, I extends Parameter & Input<V>> V getValue(I value) {
return doGetValue(value);
}
private <V, I extends Input<V>> V doGetValue(I value) { ... }
如果基本方法是这样声明的:
<V, I extends Input<V> & Column> V getValue(I value);
<V, I extends Input<V> & Parameter> V getValue(I value);
您只能按如下方式实现它们的擦除:
@Override
public Object getValue(Input value) { ... }
由于这些选项看起来都不是很好,我建议您按照以下方式重新设计您的代码:
public interface Input<R, V> {
// ...
}
public interface ObjectSet<R> {
<V> V getValue(Input<R, V> input);
}
public class ObjectSetImpl<R> implements ObjectSet<R> {
@Override
public <V> V getValue(Input<R, V> input) {
// ...
}
}
现在您可以轻松创建ObjectSet
只接受Input
特定类型参数的实例R
:
public interface Column<V> extends Input<Column<?>, V> {}
ObjectSet<Column<?>> columnSet = new ObjectSetImpl<>();
如果您不喜欢写作ObjectSet<Column<?>>
,您可以创建一个名称更好的实现ObjectSet<Column<?>>
,将所有工作委托给ObjectSetImpl
:
public class ColumnSet extends DelegatingObjectSet<Column<?>> {}
ColumnSet columnSet = new ColumnSet();
在哪里DelegatingObjectSet
:
abstract class DelegatingObjectSet<R> implements ObjectSet<R> {
// you can use dependency injection here
private final ObjectSet<R> delegate = new ObjectSetImpl<>();
@Override
public <V> V getValue(Input<R, V> input) {
return delegate.getValue(input);
}
}