英文:
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 Dogcan 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论