为什么我们不能在函数式接口中重载抽象方法? (Java)
Why can't we overload a abstract method in a functional interface? (Java)
所以我熟悉 java 中的函数式接口,以及它们与 lambda 表达式的用法。一个函数式接口只能包含一个抽象方法。从 lambda 表达式中使用这个单独的方法时,您不需要指定它的名称 - 因为接口中只有一个抽象方法,编译器知道这是您引用的方法。
示例:
// Functional Interface:
@FunctionalInterface
public interface Ball
{
void hit();
}
// Lambda to define, then run the hit method:
Ball b = () -> System.out.println("You hit it!");
b.hit();
虽然很明显为什么函数式接口只能包含一个抽象方法,但我不明白为什么不能重载该方法。
例如,以下将不会编译:
// (NOT) Functional Interface:
@FunctionalInterface
public interface Ball
{
void hit();
void hit(boolean miss);
}
// Lambda to define, then run the hit method:
Ball b = () -> System.out.println("You hit it!");
Ball ba = (boolean miss) -> System.out.println(miss);
b.hit();
ba.hit(false);
编译器声明 Ball
接口不起作用,因为它包含多个方法,但在这种情况下,我不明白为什么会出现问题 - 只要这两种方法采用不同的方法参数,应该可以根据我定义的参数推断出我在 lambda 中引用的方法。
谁能解释一下为什么不能在函数式接口中重载抽象方法?
在没有方法重载的语言中,方法由它们的名称唯一标识 class(暂时忽略覆盖)。
在 Java 中有些不同。引用自 oracle docs:
Overloading Methods
The Java programming language supports overloading methods, and Java can distinguish between methods with different method signatures. This means that methods within a class can have the same name if they have different parameter lists (there are some qualifications to this that will be discussed in the lesson titled "Interfaces and Inheritance").
所以我们知道方法也由它们的签名来标识。如果两个方法共享一个名称但没有相同的签名,则它们是不同的方法。不要让他们的共同名字让您误以为他们有某种关联。
考虑到这个事实,我们可以很容易地创建一个示例,如果方法按照您描述的方式运行,则会发生未定义的行为:
Ball ba = (boolean miss) -> System.out.println(miss);
someFunction(ba)
public void someFunction(Ball ball) {
ball.hit();
}
在这种情况下,您期望出现什么行为?这是未定义的!
不过,您可以使用 default methods。我不太了解你的情况,无法判断这是否是一种合适的方法,但你可以这样做:
@FunctionalInterface
public interface Ball
{
default void hit() {
hit(true);
}
void hit(boolean miss);
}
在 documentation for FunctionalInterface
:
中解释了为什么这有效
Conceptually, a functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract
只要声明实现了Ball
接口的class,就必须实现所有的抽象方法。
例如,如果您这样做:
Ball b = () -> System.out.println("You hit it!");
然后你传b
作为参数,其他代码调用b.hit(true)
,它会崩溃,因为hit(boolean miss)
没有实现。
所以一个函数式接口必须只有一个抽象方法。
所以我熟悉 java 中的函数式接口,以及它们与 lambda 表达式的用法。一个函数式接口只能包含一个抽象方法。从 lambda 表达式中使用这个单独的方法时,您不需要指定它的名称 - 因为接口中只有一个抽象方法,编译器知道这是您引用的方法。
示例:
// Functional Interface:
@FunctionalInterface
public interface Ball
{
void hit();
}
// Lambda to define, then run the hit method:
Ball b = () -> System.out.println("You hit it!");
b.hit();
虽然很明显为什么函数式接口只能包含一个抽象方法,但我不明白为什么不能重载该方法。
例如,以下将不会编译:
// (NOT) Functional Interface:
@FunctionalInterface
public interface Ball
{
void hit();
void hit(boolean miss);
}
// Lambda to define, then run the hit method:
Ball b = () -> System.out.println("You hit it!");
Ball ba = (boolean miss) -> System.out.println(miss);
b.hit();
ba.hit(false);
编译器声明 Ball
接口不起作用,因为它包含多个方法,但在这种情况下,我不明白为什么会出现问题 - 只要这两种方法采用不同的方法参数,应该可以根据我定义的参数推断出我在 lambda 中引用的方法。
谁能解释一下为什么不能在函数式接口中重载抽象方法?
在没有方法重载的语言中,方法由它们的名称唯一标识 class(暂时忽略覆盖)。
在 Java 中有些不同。引用自 oracle docs:
Overloading Methods
The Java programming language supports overloading methods, and Java can distinguish between methods with different method signatures. This means that methods within a class can have the same name if they have different parameter lists (there are some qualifications to this that will be discussed in the lesson titled "Interfaces and Inheritance").
所以我们知道方法也由它们的签名来标识。如果两个方法共享一个名称但没有相同的签名,则它们是不同的方法。不要让他们的共同名字让您误以为他们有某种关联。
考虑到这个事实,我们可以很容易地创建一个示例,如果方法按照您描述的方式运行,则会发生未定义的行为:
Ball ba = (boolean miss) -> System.out.println(miss);
someFunction(ba)
public void someFunction(Ball ball) {
ball.hit();
}
在这种情况下,您期望出现什么行为?这是未定义的!
不过,您可以使用 default methods。我不太了解你的情况,无法判断这是否是一种合适的方法,但你可以这样做:
@FunctionalInterface
public interface Ball
{
default void hit() {
hit(true);
}
void hit(boolean miss);
}
在 documentation for FunctionalInterface
:
Conceptually, a functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract
只要声明实现了Ball
接口的class,就必须实现所有的抽象方法。
例如,如果您这样做:
Ball b = () -> System.out.println("You hit it!");
然后你传b
作为参数,其他代码调用b.hit(true)
,它会崩溃,因为hit(boolean miss)
没有实现。
所以一个函数式接口必须只有一个抽象方法。