TL;DR 有没有办法强制方法接收子类而不是父类?
假设我有一个像这样的界面:
interface MyInterface<T extends A>{
process(A a)
}
和类(class)
abstract class A<T extends A>{
MyInteface<T>[] processors
}
还有两个子类 B 和 C,例如:
class B extends A<B>{}
class C extends A<C>{}
我想让 MyInterface 的实现可以执行以下操作:
class MyImplementation implements MyInterface<B>, MyInterface<C>{
process(B)
process(C)
}
我相信这是不可能的,因为如果您将父类(super class) A 传递给 MyImplementation,编译器将无法告诉要做什么。
是否可以强制 MyImplementation 仅接收子类?如果没有,您将如何解决这个问题?
最佳答案
这是不可能的,因为 type erasure在Java中:在运行时,与泛型相关的类型信息不再可用。例如:
List<Number> numbers = new ArrayList<>();
List<String> strings = new ArrayList<>();
// At runtime, these types actually look like this:
List numbers = new ArrayList();
List strings = new ArrayList();
因此,单个类不能使用不同的泛型类型参数多次实现相同的泛型接口(interface)。因此,class MyImplementation implements MyInterface<B>, MyInterface<C> { /* ... */ }
编译时会失败。这样做会导致以下错误:
The interface
MyInterface
cannot be implemented more than once with different arguments:MyInterface<C>
andMyInterface<B>
一旦类型被删除,这个类就等于 class MyImplementation implements MyInterface, MyInterface { /* ... */ }
,这在 Java 中显然是不允许的。
替代方案
看起来好像您正在寻找要更改的调用功能,具体取决于用于处理元素的类( MyInterface<B>
、 MyInterface<C>
等)以及处理的元素( A
、 B
、 C
等)。这称为double-dispatch并且与 Visitor Pattern 密切相关。针对您的问题,您可以执行以下操作:
public interface Element {
public void accept(Processor processor);
}
public class A implements Element {
@Override
public void accept(Processor processor) {
processor.process(this);
}
}
public class B implements Element {
@Override
public void accept(Processor processor) {
processor.process(this);
}
}
public interface Processor {
public void process(A a);
public void process(B b);
}
public class RedProcessor implements Processor {
@Override
public void process(A a) {
System.out.println("Red processor got an A");
}
@Override
public void process(B b) {
System.out.println("Blue processor got an A");
}
}
public class BlueProcessor implements Processor {
@Override
public void process(A a) {
System.out.println("Blue processor got an A");
}
@Override
public void process(B b) {
System.out.println("Blue processor got an A");
}
}
可以使用以下方法测试此代码:
Processor processor = new RedProcessor();
A a = new A();
processor.process(a);
改变Processor
实现(例如 RedProcessor
或 BlueProcessor
)和 Element
实现(例如 A
或 B
)会导致不同的输出。由于结果取决于 Processor
和 Element
,这种技术称为双-dispatch。
关于java - 如何强制子类作为参数(或不允许父类作为参数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49662380/