使用抽象中的通用参数覆盖方法 Class
Overriding Method with Generic Parameters from Abstract Class
我无法编译需要覆盖抽象 class 超类型方法的方法,该超类型使用泛型作为其中一个参数。编译器抱怨扩展 class' setRef() 方法没有覆盖超类型的方法。
父摘要Class:
public abstract class AbsClass<Q extends Interf> {
public abstract Ref<? extends AbsClass<Q>> getRef();
public abstract <M extends AbsClass<Q>> void setRef(Ref<M> newRef);
}
参考是:
public interface Ref<M extends AbsClass<? extends Interf>> { }
Interf 是:
public interface Interf { }
扩展子 Class(setRef() 不编译):
public class ChildClass extends AbsClass<InterfImpl> {
@Override
public Ref<ChildClass> getRef() {
return null;
}
@Override
public <M extends ChildClass> void setRef(Ref<M> newRef) {
return null;
}
}
我也尝试过使用通配符,但收到了同样的错误。使用通配符,抽象 class' setRef() 是:
public abstract void setRef(Ref<? extends AbsClass<Q>> newRef);
扩展 class' setRef() 是:
public void setRef(Ref<ChildClass> newRef)
甚至:
public void setRef(Ref<? extends ChildClass> newRef)
我能让它编译的唯一方法是扩展 class' setRef() 使用抽象 class' 类型:
public <M extends AbsClass<Interf>> void setRef(Ref<M> newRef)
但我想将 newRef 参数的类型限制为 Ref<ChildClass>
或子类型,因此这并不完美。如何让我的扩展 class 只允许 ChildClass 或其子类型用于 setRef() 方法的 newRef 参数?我的部分困惑是 ChildClass' getRef() return 值可以很好地处理通用类型,而 setRef() 参数上的相同 "signature" 无法编译。帮助?谢谢!
您遇到错误,因为在 AbsClass.setRef()
中,您的参数类型为 Ref<? extends AbsClass<Q>>
但是在你的 ChildClass.setRef()
中,参数的类型是 Ref<? extends ChildClass>
。
对于重写,子类在方法中的类型参数应与其父类相同(在使用泛型时进行类型擦除之前)。
setRef
的问题是您可以通过类型 AbsClass<? extends Interf>
的变量访问 ChildClass
的实例,因此 setRef
的参数类型看起来像<M extends AbsClass<? extends Interf>>
又可以是任何 M
但也不匹配 <M extends AbsClass<Q>>
因为 Q
在您的情况下被定义为 InterfImpl
。
您可以将 ChildClass
更改为:
public <M extends AbsClass<InterfImpl>> void setRef(Ref<M> newRef)
但这仍然允许任何 M
并且你不能只使用 Ref<ChildClass>
因为我上面说的,即编译器不会知道 Ref<ChildClass>
如果你使用AbsClass<InterfImpl>
甚至 AbsClass<? extends InterfImpl>
.
类型的变量
仅允许 ChildClass
参数的一种方法是在泛型类型中也使用 ChildClass
,例如像这样:
public abstract class AbsClass<Q extends Interf, M extends AbsClass<Q, M>> {
public abstract Ref<M> getRef();
public abstract void setRef(Ref<M> newRef);
}
public class ChildClass extends AbsClass<InterfImpl, ChildClass> {
public Ref<ChildClass> getRef() { return null; }
public void setRef(Ref<ChildClass> newRef) { }
}
我无法编译需要覆盖抽象 class 超类型方法的方法,该超类型使用泛型作为其中一个参数。编译器抱怨扩展 class' setRef() 方法没有覆盖超类型的方法。
父摘要Class:
public abstract class AbsClass<Q extends Interf> {
public abstract Ref<? extends AbsClass<Q>> getRef();
public abstract <M extends AbsClass<Q>> void setRef(Ref<M> newRef);
}
参考是:
public interface Ref<M extends AbsClass<? extends Interf>> { }
Interf 是:
public interface Interf { }
扩展子 Class(setRef() 不编译):
public class ChildClass extends AbsClass<InterfImpl> {
@Override
public Ref<ChildClass> getRef() {
return null;
}
@Override
public <M extends ChildClass> void setRef(Ref<M> newRef) {
return null;
}
}
我也尝试过使用通配符,但收到了同样的错误。使用通配符,抽象 class' setRef() 是:
public abstract void setRef(Ref<? extends AbsClass<Q>> newRef);
扩展 class' setRef() 是:
public void setRef(Ref<ChildClass> newRef)
甚至:
public void setRef(Ref<? extends ChildClass> newRef)
我能让它编译的唯一方法是扩展 class' setRef() 使用抽象 class' 类型:
public <M extends AbsClass<Interf>> void setRef(Ref<M> newRef)
但我想将 newRef 参数的类型限制为 Ref<ChildClass>
或子类型,因此这并不完美。如何让我的扩展 class 只允许 ChildClass 或其子类型用于 setRef() 方法的 newRef 参数?我的部分困惑是 ChildClass' getRef() return 值可以很好地处理通用类型,而 setRef() 参数上的相同 "signature" 无法编译。帮助?谢谢!
您遇到错误,因为在 AbsClass.setRef()
中,您的参数类型为 Ref<? extends AbsClass<Q>>
但是在你的 ChildClass.setRef()
中,参数的类型是 Ref<? extends ChildClass>
。
对于重写,子类在方法中的类型参数应与其父类相同(在使用泛型时进行类型擦除之前)。
setRef
的问题是您可以通过类型 AbsClass<? extends Interf>
的变量访问 ChildClass
的实例,因此 setRef
的参数类型看起来像<M extends AbsClass<? extends Interf>>
又可以是任何 M
但也不匹配 <M extends AbsClass<Q>>
因为 Q
在您的情况下被定义为 InterfImpl
。
您可以将 ChildClass
更改为:
public <M extends AbsClass<InterfImpl>> void setRef(Ref<M> newRef)
但这仍然允许任何 M
并且你不能只使用 Ref<ChildClass>
因为我上面说的,即编译器不会知道 Ref<ChildClass>
如果你使用AbsClass<InterfImpl>
甚至 AbsClass<? extends InterfImpl>
.
仅允许 ChildClass
参数的一种方法是在泛型类型中也使用 ChildClass
,例如像这样:
public abstract class AbsClass<Q extends Interf, M extends AbsClass<Q, M>> {
public abstract Ref<M> getRef();
public abstract void setRef(Ref<M> newRef);
}
public class ChildClass extends AbsClass<InterfImpl, ChildClass> {
public Ref<ChildClass> getRef() { return null; }
public void setRef(Ref<ChildClass> newRef) { }
}