java 在泛型方法中使用它(继承)

java using this in generic method (inheritance)

我试图在创建 lambda 时访问子 class 方法和字段,它在父 class 中使用。代码更容易解​​释:

class Parent {
    List<Processor<? extends Parent>> processors;

    private void doSmth() {
        for (Processor<? extends Parent> processor : processors) {
            processor.doJob(this);  //this lines gives compile error
        }
    }

    public void registerListeners(Processor<? extends Parent> ... subscribers) {
        this.subscriberList = Arrays.asList(subscribers);
    }
}

其中 ProcessorFunctionalInterface.

public interface Processor<T extends Parent> extends BiFunction<T, Message,  Boolean> {
    AtomicReference<Boolean> ok = new AtomicReference<>(false);

    default void doJob(T client, Message message) {
        if (apply(client, message))
            ok.set(true);
    }

    default boolean isDone() {
        return ok.get();
    }
}

这些 classes 的想要用法示例:

Child childInstance= new Child(); //where Child class extends Parent
childInstance.registerListeners((child, message) -> child.callSomeChildMethod());
childInstance.doSmth(message);

创建 lambda 而无需冗余指定参数类型真的很酷:

childInstance.registerListeners((Processor<Child>) (child, message) -> child.callSomeChildMethod());

(因为它总是应该是我注册听众的类型)
问题是代码没有编译错误
incompatible types: Parent cannot be converted to capture#1 of ? extends Parent
,这是很合逻辑的(我明白原因)。 java 有什么方法可以让这段代码正常工作吗?
提前致谢!

您可以简单地强制转换 processor 对象来声明您要向它传递一个派生自 Parent 的 class 的对象(可能是 Child) , 并将 this 转换为相同的类型。它甚至可以是通用的:

private <T extends Parent> void doSmth() {
    for (Processor<? extends Parent> p : processors) {
        Processor<T> processor = (Processor<T>) p; // explicit cast
        processor.doJob((T) this);  //no compile error
    }
}

你在 Parent class 中加入 List<Processor<? extends Parent>> processors; 的想法是不可取的。如您所见,由于您没有提到列表中的进程类型;无论你在哪里调用 processor.doJob(anyObjectHere) 都会抛出一个错误,无论是哪种方式(除非你进行显式转换)

尝试做这样的事情;

  1. 声明一个 Client 而不是你的 Parent 来保存 List<Processor<? extends Parent>> processors;

    中的处理器类型
    abstract class Client<T extends Client<T>> {
        List<Processor<T>> processors;
    
        public void doSmth(Message message) {
            for (Processor<T> processor : processors) {
                processor.doJob(getThis(), message);  
            }
        }
    
        abstract T getThis();
    
        public void registerListeners(Processor<T> subscribers) {
            this.processors = Arrays.asList(subscribers);
        }
    }
    
  2. 将您的 Processor 定义更改为包含 Client 而不是 Parent

    interface Processor<T extends Client<T>> extends BiFunction<T, Message,  Boolean> {
        AtomicReference<Boolean> ok = new AtomicReference<>(false);
    
        default void doJob(T client, Message message) {
            if (apply(client, message))
                ok.set(true);
        }
    
        default boolean isDone() {
            return ok.get();
        }
    }
    
  3. 现在您可以像这样创建您的 Child

    class Child extends Client<Child> {
        boolean callSomeChildMethod() {
            return true;
        }
    
        @Override
        Child getThis() {
            return this;
        }
    }
    
  4. 并像以前一样称呼它们;

        Child childInstance= new Child(); //where Child class extends Parent
        childInstance.registerListeners((child, message) -> child.callSomeChildMethod());
        childInstance.doSmth(message);
    

这样你既没有编译错误也没有警告