Java 具有扩展类型的 Lambda 函数馈送
Java Lambda function feeding with extend type
Eclipse 告诉我:
interface Recursive
{
List<? extends Recursive> getSubitems();
default void processRecursive(Consumer<? extends Recursive> f)
{
f.accept(this);
for (Recursive r : getSubitems())
f.accept(r);
}
}
不可能(f.accept(this) 和 f.accept(r) 错误:Consumer 类型中的方法 accept(capture#1-of ? extends Recursive) 不适用于参数(递归))
我想知道为什么,因为这将扩展 Recursive,所以 r(递归)也将扩展,并且它们可以作为 Recursives 处理..
在我看来,这是完全合理且可预测的行为。
假设您有两个 类 实现接口:Foo
和 Bar
Consumer<Bar> barConsumer = ...
Foo foo = new Foo();
foo.processRecursive(barConsumer);
现在,根据方法签名,processRecursive()
调用是有效的,因为 barConsumer
适合 Consumer<? extends Recursive>
。
但是,代码 f.accept(this)
会尝试将 Foo
对象发送到 Comsumer
,从而违反 Consumer<Bar>
。这就是编译器抱怨的原因,因为它不能保证类型安全,即只向 accept()
方法提供有效对象。
由于无法强制 this
是 Recursive
的正确子类型,因此没有 type-safe 方法来做到这一点。
如果您可以牺牲 一些 类型安全,您可以将 Recursive
设为泛型:
interface Recursive<T extends Recursive> {
List<T> getSubitems();
default void processRecursive(Consumer<T> consumer) {
consumer.accept((T) this); // sacrificing type-safety
for (T item : getSubitems())
consumer.accept(item);
}
}
现在可以点赞了,与世无争:
class Foo implements Recursive<Foo> {
但是有人可以写这个,破坏代码,因为现在 this
不是 Bar
,所以转换会在运行时抛出异常 (也许,取决于 Java 版本我相信):
class Foo implements Recursive<Bar> {
Eclipse 告诉我:
interface Recursive
{
List<? extends Recursive> getSubitems();
default void processRecursive(Consumer<? extends Recursive> f)
{
f.accept(this);
for (Recursive r : getSubitems())
f.accept(r);
}
}
不可能(f.accept(this) 和 f.accept(r) 错误:Consumer 类型中的方法 accept(capture#1-of ? extends Recursive) 不适用于参数(递归))
我想知道为什么,因为这将扩展 Recursive,所以 r(递归)也将扩展,并且它们可以作为 Recursives 处理..
在我看来,这是完全合理且可预测的行为。
假设您有两个 类 实现接口:Foo
和 Bar
Consumer<Bar> barConsumer = ...
Foo foo = new Foo();
foo.processRecursive(barConsumer);
现在,根据方法签名,processRecursive()
调用是有效的,因为 barConsumer
适合 Consumer<? extends Recursive>
。
但是,代码 f.accept(this)
会尝试将 Foo
对象发送到 Comsumer
,从而违反 Consumer<Bar>
。这就是编译器抱怨的原因,因为它不能保证类型安全,即只向 accept()
方法提供有效对象。
由于无法强制 this
是 Recursive
的正确子类型,因此没有 type-safe 方法来做到这一点。
如果您可以牺牲 一些 类型安全,您可以将 Recursive
设为泛型:
interface Recursive<T extends Recursive> {
List<T> getSubitems();
default void processRecursive(Consumer<T> consumer) {
consumer.accept((T) this); // sacrificing type-safety
for (T item : getSubitems())
consumer.accept(item);
}
}
现在可以点赞了,与世无争:
class Foo implements Recursive<Foo> {
但是有人可以写这个,破坏代码,因为现在 this
不是 Bar
,所以转换会在运行时抛出异常 (也许,取决于 Java 版本我相信):
class Foo implements Recursive<Bar> {