Java 实现两个接口并解决默认方法冲突:为什么要使用 super 关键字?
Java implementing two interfaces and resolving default method conflicts: why using super keyword?
Java 解决默认方法冲突:为什么使用 super 关键字?
我正在看书 "Core Java SE 9 for the impatient"。在部分
"Resolving Default Method Conflicts",我发现解析的时候
默认方法冲突,使用 super 关键字。但我不
理解为什么使用 super
关键字。
来自这个link:https://docs.oracle.com/javase/tutorial/java/IandI/override.html
我知道 super
关键字是必需的(否则程序将无法编译)。
但这似乎违反直觉。据我了解,界面
“Identified
”没有超 class。为什么不直接使用“return Identified.getId();
”?
public interface Person {
default int getId() {
return 0;
}
}
public interface Identified {
default int getId() {
return Math.abs(hashCode());
}
}
public class Employee implements Person, Identified {
public int getId() {
return Identified.super.getId();
}
}
此 question and this question 中有一些解释,但其中 none 解释了为什么使用关键字 super
。
因为 Identified.getId()
意味着 getId
是一个 static
方法。在Java8之前,这个super
关键字只是用来引用一个超级class,形式是super.getId()
.
在你的情况下,Identified.super.getId()
并不意味着 "The getId() of the super of Identified",而是 "The getId() of the super that is from Identified"。
因为 Indentified.getId()
语法已经用于静态方法调用。 C++ 语法 Identifier::getId()
本来可以很好,但是 Java 将它用于方法引用,因此 no-go 也是如此。 Identified.this.getId()
语法也不能使用,因为当您嵌套了 classes.
时,它已经用于从外部 class 调用方法
我想在某些时候他们只是 运行 没有选择。但我同意语法可能有点误导,但由于在 Java 中你不能调用 "grandparent" 方法,因此使用 "super" 可能被视为较小的邪恶。
很明显Employee
有冲突; Person
和 Identified
的方法签名 default int getId()
相同.
JLS 9.4.1.3 将此描述为导致错误的行为冲突。当然,您必须决定应该调用哪个 getId()
方法(覆盖它,或者从 Person
或 Identified
中选择默认实现。
JLS 9.4.1.1 (Overriding by Instance Methods) 提供了一个线索:
An overridden default method can be accessed by using a method
invocation expression (§15.12) that contains the keyword super
qualified by a superinterface name.
但是使用 super
这个词的最正式的原因来自 JLS 15.12,特别是 15.12.1:Compile-Time 第 1 步:确定 Class 或接口搜索
该部分描述了方法调用可以采用的 6 形式。
一种形式是 Identified.getId()
保留用于静态引用,并在另一个答案中讨论。
另一种形式是super.getId()
。这是super
这个词更常见的用法;它指的是 class.
的 superclass
这导致15.12.1中提到的最终形式:TypeName.super.getId()
超级这个词在这里只有一个目的。如果单词 super 出现在方法 getId() 的左侧,并且如果 TypeName 出现在 super 的左侧,则 (i) TypeName 必须是 class 或接口,(ii) 如果 TypeName 是 class 它优先于接口,(iii) 如果 TypeName 不是 class 它必须是一个接口。
所以这最终导致了在这种情况下对super的解释:
Super 在这种情况下用于 匹配形式 TypeName.super.identifier
这是定义的方式(由 JLS 15.12. 1) 从接口 TypeName.
调用方法标识符
Java 解决默认方法冲突:为什么使用 super 关键字?
我正在看书 "Core Java SE 9 for the impatient"。在部分
"Resolving Default Method Conflicts",我发现解析的时候
默认方法冲突,使用 super 关键字。但我不
理解为什么使用 super
关键字。
来自这个link:https://docs.oracle.com/javase/tutorial/java/IandI/override.html
我知道 super
关键字是必需的(否则程序将无法编译)。
但这似乎违反直觉。据我了解,界面
“Identified
”没有超 class。为什么不直接使用“return Identified.getId();
”?
public interface Person {
default int getId() {
return 0;
}
}
public interface Identified {
default int getId() {
return Math.abs(hashCode());
}
}
public class Employee implements Person, Identified {
public int getId() {
return Identified.super.getId();
}
}
此 question and this question 中有一些解释,但其中 none 解释了为什么使用关键字 super
。
因为 Identified.getId()
意味着 getId
是一个 static
方法。在Java8之前,这个super
关键字只是用来引用一个超级class,形式是super.getId()
.
在你的情况下,Identified.super.getId()
并不意味着 "The getId() of the super of Identified",而是 "The getId() of the super that is from Identified"。
因为 Indentified.getId()
语法已经用于静态方法调用。 C++ 语法 Identifier::getId()
本来可以很好,但是 Java 将它用于方法引用,因此 no-go 也是如此。 Identified.this.getId()
语法也不能使用,因为当您嵌套了 classes.
我想在某些时候他们只是 运行 没有选择。但我同意语法可能有点误导,但由于在 Java 中你不能调用 "grandparent" 方法,因此使用 "super" 可能被视为较小的邪恶。
很明显Employee
有冲突; Person
和 Identified
的方法签名 default int getId()
相同.
JLS 9.4.1.3 将此描述为导致错误的行为冲突。当然,您必须决定应该调用哪个 getId()
方法(覆盖它,或者从 Person
或 Identified
中选择默认实现。
JLS 9.4.1.1 (Overriding by Instance Methods) 提供了一个线索:
An overridden default method can be accessed by using a method invocation expression (§15.12) that contains the keyword super qualified by a superinterface name.
但是使用 super
这个词的最正式的原因来自 JLS 15.12,特别是 15.12.1:Compile-Time 第 1 步:确定 Class 或接口搜索
该部分描述了方法调用可以采用的 6 形式。
一种形式是 Identified.getId()
保留用于静态引用,并在另一个答案中讨论。
另一种形式是super.getId()
。这是super
这个词更常见的用法;它指的是 class.
这导致15.12.1中提到的最终形式:TypeName.super.getId()
超级这个词在这里只有一个目的。如果单词 super 出现在方法 getId() 的左侧,并且如果 TypeName 出现在 super 的左侧,则 (i) TypeName 必须是 class 或接口,(ii) 如果 TypeName 是 class 它优先于接口,(iii) 如果 TypeName 不是 class 它必须是一个接口。
所以这最终导致了在这种情况下对super的解释:
Super 在这种情况下用于 匹配形式 TypeName.super.identifier
这是定义的方式(由 JLS 15.12. 1) 从接口 TypeName.