英文:
Why does Function<Interface, R> not accept a method reference from a subclass?
问题
以下是翻译好的内容:
假设我有一个接口 Animal
,其中有一个方法 String getRace()
,还有一个子类 Dog
。我将一些动物存储在一个 List<Animal>
中。
现在,如果我想对该列表进行排序,并将一个 Function<Animal, String>
传递到方法中,以便与 Comparator.comparing(...)
一起使用,那么这将正常工作。然而,如果我从 Dog
中引用一个函数作为参数传递,编译器会抛出以下错误:
类型 Zoo.Dog 在这里没有定义适用的 getRace(Zoo.Animal)。
尽管它是 Animal
的子类,并且确实定义了该函数。
以下是代码:
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class Zoo {
public interface Animal {
public String getRace();
}
public class Dog implements Animal {
public String getRace() {
return "Some race";
}
}
private List<Animal> animals = Arrays.asList(new Animal[] {});
public void sort(Function<Animal, String> function) {
animals = animals.stream().sorted(Comparator.comparing(function)).collect(Collectors.toList());
}
public static void main(String[] args) {
Zoo zoo = new Zoo();
// 错误:"类型 Zoo.Dog 在这里没有定义适用的 getRace(Zoo.Animal)"
zoo.sort(Dog::getRace);
}
}
为什么会这样呢?
我在这个问题中找到了类似的情况,但在那个示例中,这些类之间没有关联。
英文:
Let's say I have an interface Animal
with the method String getRace()
and a subclass Dog
. I keep some animals in a List<Animal>
.
Now if I wanted to sort that list and passed a Function<Animal, String>
into the method to use it together with Comparator.comparing(...)
that would work fine. However, if I reference a function from Dog
to pass as an argument, the compiler throws the following error:
> The type Zoo.Dog does not define getRace(Zoo.Animal) that is applicable here.
even though it's a subclass of Animal
and does define that function.
Here's the code:
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class Zoo {
public interface Animal {
public String getRace();
}
public class Dog implements Animal {
public String getRace() {
return "Some race";
}
}
private List<Animal> animals = Arrays.asList(new Animal[] {});
public void sort(Function<Animal, String> function) {
animals = animals.stream().sorted(Comparator.comparing(function)).collect(Collectors.toList());
}
public static void main(String[] args) {
Zoo zoo = new Zoo();
// Error: "The type Zoo.Dog does not define getRace(Zoo.Animal) that is applicable here"
zoo.sort(Dog::getRace);
}
}
Why is that?
I've found this question, but in that example the classes are in no relation to each other.
答案1
得分: 1
Dog::getRace
需要一个 Dog
实例,但是 animals.stream()
提供了 Animal
实例。
我猜应该能工作,因为 Dog
实现了 Animal
,而且 getRace
在 Animal
中声明:
zoo.sort(Animal::getRace);
英文:
Dog::getRace
expects a Dog
instance, but animals.stream()
provides Animal
instances.
What should work, I guess, since Dog
implements Animal
and getRace
is declared in Animal
:
zoo.sort(Animal::getRace);
答案2
得分: 1
这是有效的代码:
public static void main(String[] args) {
Zoo zoo = new Zoo();
zoo.sort(Animal::getRace);
}
原因很简单:
要使用Comparator
对Animal
的列表进行排序,它需要是一个Comparator<Animal>
。这意味着您传递给Comparator.comparing
的函数需要是一个Function<? super Animal, ? extends Comparable>
。然而,对于Function<Dog, String>
来说并不成立,但对于Function<Animal, String>
和Function<Object, String>
来说是成立的。
您正确地定义了.sort()
来接受Function<Animal, String>
,但您传递了一个Dog
的成员函数 - 实质上是一个函数Dog -> String
,或者在函数式接口中是Function<Dog, String>
。
用不太技术性的说法:是的,Dog
可以做的事情Animal
也能做。然而,反过来却不成立 - Dog
可以有一些并非所有动物都有的函数。因此,在Function<Animal, ?>
的位置使用Function<Dog, ?>
是无效的 - 但反过来是可以的。
英文:
This works:
public static void main (String[] args) {
Zoo zoo = new Zoo();
zoo.sort(Animal::getRace);
}
The reason is simple:
To sort a List of Animal
using a Comperator
, it needs to be a Comperator<Animal>
. This means the function you pass into Comperator.comparing
needs to
be of a Function<? super Animal,? extends Comperable>
. This is not
true for Function<Dog, String>
, however it is true for
Function<Animal, String>
and Function<Object, String>
.
You correctly define your .sort()
to take a Function<Animal, String>
- but you pass in a member function of Dog
- this is essentialla a Function Dog -> String
, or Function<Dog,String>
in functional interfaces.
In less technical terms: yes, a Dog
can do everything an Animal
can. The way around however is not true - a Dog
can have a function that not all animals have. Therefore, it's not valid to use a Function<Dog,?>
in place of a Function<Animal,?>
- but it would be ok the way around.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论