这是我基本上想要的代码,它不会编译:
interface Interface {
interface ArgumentInterface {
// Some methods
}
void doCallback(Consumer<? super ArgumentInterface> callback);
}
interface SubInterface extends Interface {
interface ArgumentSubInterface extends ArgumentInterface {
// Some more methods
}
@Override
void doCallback(Consumer<? super ArgumentSubInterface> callback);
}
这里的想法是Interface将ArgumentInterface的实例传递给用户提供的Consumer,而SubInterface将传递更具体的ArgumentSubInterface的实例。特别是,我希望用户能够传递Consumer&lt; ArgumentSubInterface&gt;到SubInterface.doCallback(),并有这个工作。
天真地,似乎这样应该按原样工作:接口版本接受的任何参数也将被SubInterface的版本接受。但是,Java声称该方法不会覆盖。
答案 0 :(得分:5)
它不起作用,因为Java doesn't allow overrides with contravariant parameters。您可以做的是使用您要接受的特定类型interface ArgumentInterface {
// Some methods
}
interface Interface<IFace extends ArgumentInterface> {
void doCallback(Consumer<IFace> callback);
}
interface ArgumentSubInterface extends ArgumentInterface {
// Some more methods
}
interface SubInterface<IFace extends ArgumentSubInterface>
extends Interface<IFace> {
// No need to override anymore, the selection is applied at the
// SubInterface generics' arguments
// @Override
// void doCallback(Consumer<? super ArgumentSubInterface> callback);
}
参数化Interface
:
ArgumentInterface
答案 1 :(得分:1)
您说“Interface
版本接受的任何论据也将被SubInterface
的版本接受”。这是正确的,但不是方法重写的方式。就像你写的那样:
interface Interface {
void method(String s);
}
interface SubInterface extends Interface {
void method(Object o);
}
虽然method(Object)
能够接受method(String)
可以接受的任何内容,但它仍然不会覆盖该方法。在这个简化的示例中,您可以将问题解决为
interface SubInterface extends Interface {
@Override default void method(String s) {
method((Object)s);
}
void method(Object o);
}
具有SubInterface
实现者必须使用更抽象类型实现一个method
的预期效果。
但是,当有问题的参数类型为Consumer<? super ArgumentInterface>
和Consumer<? super ArgumentSubInterface>
时,我们无法提供重载方法,因为在类型擦除后,两种方法都具有参数类型Consumer
,这是不允许。所以唯一的解决方法是使用与众不同的方法而不是重载:
interface Interface {
interface ArgumentInterface {
// Some methods
}
void doCallback(Consumer<? super ArgumentInterface> callback);
}
interface SubInterface extends Interface {
interface ArgumentSubInterface extends ArgumentInterface {
// Some more methods
}
@Override
default void doCallback(Consumer<? super ArgumentInterface> callback) {
doCallbackSub(callback);
}
void doCallbackSub(Consumer<? super ArgumentSubInterface> callback);
}
我想,这不是最好的想象,但是你可以用Java Generics获得最好的结果......
答案 2 :(得分:0)
typealias ProtocolArray<ProtocolType: Protocol> = Array<ProtocolType.T>
struct Struct<ProtocolType: Protocol> {
func doSomething(with: ProtocolArray<ProtocolType>) {
let _ = with.map { $0 } // no complaints
}
}