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);
}
}
其中 Processor
是 FunctionalInterface
.
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)
都会抛出一个错误,无论是哪种方式(除非你进行显式转换)
尝试做这样的事情;
声明一个 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);
}
}
将您的 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();
}
}
现在您可以像这样创建您的 Child
;
class Child extends Client<Child> {
boolean callSomeChildMethod() {
return true;
}
@Override
Child getThis() {
return this;
}
}
并像以前一样称呼它们;
Child childInstance= new Child(); //where Child class extends Parent
childInstance.registerListeners((child, message) -> child.callSomeChildMethod());
childInstance.doSmth(message);
这样你既没有编译错误也没有警告
我试图在创建 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);
}
}
其中 Processor
是 FunctionalInterface
.
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)
都会抛出一个错误,无论是哪种方式(除非你进行显式转换)
尝试做这样的事情;
声明一个
中的处理器类型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); } }
将您的
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(); } }
现在您可以像这样创建您的
Child
;class Child extends Client<Child> { boolean callSomeChildMethod() { return true; } @Override Child getThis() { return this; } }
并像以前一样称呼它们;
Child childInstance= new Child(); //where Child class extends Parent childInstance.registerListeners((child, message) -> child.callSomeChildMethod()); childInstance.doSmth(message);
这样你既没有编译错误也没有警告