java - 如何强制子类作为参数(或不允许父类作为参数)

标签 java

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> and MyInterface<B>

一旦类型被删除,这个类就等于 class MyImplementation implements MyInterface, MyInterface { /* ... */ } ,这在 Java 中显然是不允许的。

<小时/>

替代方案

看起来好像您正在寻找要更改的调用功能,具体取决于用于处理元素的类( MyInterface<B>MyInterface<C> 等)以及处理的元素( ABC 等)。这称为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实现(例如 RedProcessorBlueProcessor )和 Element实现(例如 AB )会导致不同的输出。由于结果取决于 ProcessorElement ,这种技术称为-dispatch。

关于java - 如何强制子类作为参数(或不允许父类作为参数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49662380/

相关文章:

java - 正则表达式差异

java - 使用正则表达式检测特殊字符串并仅替换其中的一部分

java - 如何从 Jmeter 执行 java 类

java - 为什么我无法调用 getActivity()?

java - 为什么 Java 不支持构造函数的类型推断?

java - 我如何选择多个链作为biojava中结构对齐的结构对象

java - Log4j配置: How to create a new folder for each day?

java - 为特定条件维护 hashCode 契约(Contract),equals() 取决于两个整数

java - 无法让 Java 编译 : cannot find file

java - 将正则表达式用于数字和带长度的字母