更改 java 8 默认方法的可见性
Changing visibility of java 8 default method
我有一个 class
(比如说 FOO
),它有一个具有 default
可见性的方法,
如下所示:
void sayHi() {}
现在,如果在扩展 class 时覆盖此方法,我无法降低它的可见性。所以我只能用default
或者public
.
public class MyClassTest extends FOO {
@Override
// Or I can use public void sayHi()
void sayHi() {
System.out.println("Overriden sayHi");
}
}
现在,如果我使用如下默认方法在 Java 8 中编写接口:
public interface InterfaceX {
// Java-8 defalu method
default String printName() {
System.out.println("Interface1 default metod");
return "Interface1 default metod";
}
}
现在,如果我在 class 中重写此方法,如果保持重写方法的可见性 default
,它应该可以编译。
public class Java8InterfaceTest implements InterfaceX{
@Override
void printHello() {
System.out.println("Printing..!");
Interface1.super.printName();
}
}
它说
Cannot reduce the visibility of the inherited method from InterfaceX
我已经知道 public
中 interface
中的每个方法默认情况下,但在上面的示例中我们使用 default
我认为是 access modifier
在 java
.
我有以下问题:
interface
中的 default
是否不同于未应用访问修饰符时提供的 default
可见性?
- 如果不同,那么它有何不同?
default
与默认可见性无关。接口中的 default
方法是在接口中具有默认实现的方法。
该方法的可见性仍然是 public
。
因此,在您的 Java8InterfaceTest
class 中实现的方法必须具有 public
可见性:
public void printHello() {
...
}
其他答案很好地概述了 "syntactical" 您关于 default 是 "visibility" 的假设的缺陷。
但背后有一个值得专门回答的概念性问题:降低方法的可见性并不是健全。
请记住:class 或接口的 pubic "API" 声明一个 contract 供客户端代码使用。比如:在基础 class/interface Animal
.
上有一个方法 eat()
重点是不同的subclasses/implementations可以提供他们自己的eat()
实现。这样你就可以拥有:
Animal whatever = ...
whatever.eat();
并且无论 ...
实际上创建了什么(可能是 Cat
、Dog
、Unicorn
)- 调用 whatever.eat()
是有效的。
你的想法是说:我想"hide"eat()
一个特定的子classDonkey
。如果你能做到这一点——突然间上面的代码可能是无效的。因为当 whatever
恰好是 Donkey
.
的实例时,whatever.eat()
不再是有效调用
长话短说:阅读 Liskov Substitution Principle 了解为什么 "taking away" public 不是一个好主意 - 完全独立于混淆 "default package protected visibility" 和
接口中的默认关键字。
我认为如果你把你的界面写成:
interface Test {
default public void go() {
}
}
这是有道理的。 default
方法仍然是 public
;与 "default" 可见性无关。
我有一个 class
(比如说 FOO
),它有一个具有 default
可见性的方法,
如下所示:
void sayHi() {}
现在,如果在扩展 class 时覆盖此方法,我无法降低它的可见性。所以我只能用default
或者public
.
public class MyClassTest extends FOO {
@Override
// Or I can use public void sayHi()
void sayHi() {
System.out.println("Overriden sayHi");
}
}
现在,如果我使用如下默认方法在 Java 8 中编写接口:
public interface InterfaceX {
// Java-8 defalu method
default String printName() {
System.out.println("Interface1 default metod");
return "Interface1 default metod";
}
}
现在,如果我在 class 中重写此方法,如果保持重写方法的可见性 default
,它应该可以编译。
public class Java8InterfaceTest implements InterfaceX{
@Override
void printHello() {
System.out.println("Printing..!");
Interface1.super.printName();
}
}
它说
Cannot reduce the visibility of the inherited method from InterfaceX
我已经知道 public
中 interface
中的每个方法默认情况下,但在上面的示例中我们使用 default
我认为是 access modifier
在 java
.
我有以下问题:
interface
中的default
是否不同于未应用访问修饰符时提供的default
可见性?- 如果不同,那么它有何不同?
default
与默认可见性无关。接口中的 default
方法是在接口中具有默认实现的方法。
该方法的可见性仍然是 public
。
因此,在您的 Java8InterfaceTest
class 中实现的方法必须具有 public
可见性:
public void printHello() {
...
}
其他答案很好地概述了 "syntactical" 您关于 default 是 "visibility" 的假设的缺陷。
但背后有一个值得专门回答的概念性问题:降低方法的可见性并不是健全。
请记住:class 或接口的 pubic "API" 声明一个 contract 供客户端代码使用。比如:在基础 class/interface Animal
.
eat()
重点是不同的subclasses/implementations可以提供他们自己的eat()
实现。这样你就可以拥有:
Animal whatever = ...
whatever.eat();
并且无论 ...
实际上创建了什么(可能是 Cat
、Dog
、Unicorn
)- 调用 whatever.eat()
是有效的。
你的想法是说:我想"hide"eat()
一个特定的子classDonkey
。如果你能做到这一点——突然间上面的代码可能是无效的。因为当 whatever
恰好是 Donkey
.
whatever.eat()
不再是有效调用
长话短说:阅读 Liskov Substitution Principle 了解为什么 "taking away" public 不是一个好主意 - 完全独立于混淆 "default package protected visibility" 和 接口中的默认关键字。
我认为如果你把你的界面写成:
interface Test {
default public void go() {
}
}
这是有道理的。 default
方法仍然是 public
;与 "default" 可见性无关。