如何保护实现接口的方法不被覆盖?
How to protect a method implementing an interface from overriding?
我有接口:
public interface Doable {
void doSomething();
}
和实现它的class:
public class DoJump() implements Doable {
@Override
private void doSomething() {
fireJumpHandler();
}
}
这是一个愚蠢的例子,但我想提出问题。
此代码无法编译,我在 Eclipse 中遇到错误 IDE:
Cannot reduce the visibility of the inherited method from
Doable
我有一个声明方法的通用接口。该方法在具体 class 中被重写。我想避免另一个可以扩展这个 class (DoJump
) 的 class,所以我想从 sub classes 中隐藏这个方法。我想使用 private
修饰符,但 Java 不允许我这样做。
为什么不可能,如何解决?
我想回答你的最后一个问题 "How to workaround it?"
,因为相关问题中没有对此进行描述。创建第二个接口 NotDoable
,它根本没有声明 doSomething()
。然后让你的 DoJump
实现这两个接口。给每个不应该覆盖 doSomething
接口 NotDoable
而不是真实类型 DoJump
的引用。然后他们就不会知道该对象确实可以 doSomething
,他们不会知道每个 class 设计。当然,可以解决这个问题,但实际上可以解决所有问题。 class 这样设计更正确。这是一些代码:
public interface Doable {
public void doSomething();
}
public interface NotDoable {
}
public class DoJump implements Doable, NotDoable {
@Override
public void doSomething() {
System.out.println("hi");
}
public NotDoable meAsNotDoable() {
return this;
}
public static void main(String[] args) {
DoJump object = new DoJump();
// This call is possible, no errors
object.doSomething();
NotDoable hidden = object.meAsNotDoable();
// Not possible, compile error, the true type is hidden!
hidden.doSomething();
}
}
但如前所述,可以使用 if (hidden instanceof DoJump) { DoJump trueObject = (DoJump) hidden; }
解决此问题。但是,也可以通过反射访问私有值。
其他 classes 现在实现 NotDoable
而不是扩展 DoJump
。如果你在这个界面声明了其他人应该知道的关于DoJump
的一切,那么他们只能做他们应该做的。您可以调用此接口 IDoJump
和实现 class DoJump
,一个常见的模式。
现在一样,更具体一点。
public interface IDog {
public void bark();
}
public interface ICanFly {
public void fly();
}
public class FlyingDog implements IDog, ICanFly {
@Override
public void bark() {
System.out.println("wuff");
}
@Override
public void fly() {
System.out.println("Whuiiii");
}
public static void main(String[] args) {
FlyingDog flyingDog = new FlyingDog();
// Both works
flyingDog.fly();
flyingDog.bark();
IDog dog = (IDog) flyingDog;
// Same object but does not work, compile error
dog.fly();
ICanFly canFly = (ICanFly) flyingDog;
// Same object but does not work, compile error
canFly.bark();
}
}
现在扩展 class。
public class LoudDog implements IDog {
@Override
public void bark() {
System.out.println("WUUUUFF");
}
// Does not work, compile error as IDog does not declare this method
@Override
public void fly() {
System.out.println("I wanna fly :(");
}
}
最后要注意,如果其他人知道他们的IDog
实际上是一个FlyingDog
(并且他们施放了它),那么他们必须能够呼唤fly()
,因为FlyingDog
必须能飞。此外,它们 必须 能够覆盖行为,只要它们遵循其 method-signature
给出的 fly()
规范。想象一个叫做 PoorFlyingDog
的 subclass
,他需要覆盖默认行为,否则他可以完美地飞行,但他是一个糟糕的飞行者。
总结:向别人隐瞒自己是DoJump
,也隐瞒自己是Doable
,假装只是NotDoable
。或者对于动物,假装只是 IDog
而不是 FlyingDog
或 ICanFly
。如果其他人不作弊(施法),他们将无法对你使用fly()
,尽管你实际上可以飞行。
将 final
添加到 DoJump
声明以防止此 class 被覆盖(因此 doSomething()
也被覆盖)。
public final class DoJump implements Doable {
@Override
public void doSomething() {
fireJumpHandler();
}
}
如果你仍然需要能够继承DoJump
但又不想doSomething()
被覆盖,在方法签名中加上final
修饰符
public class DoJump implements Doable {
@Override
public final void doSomething() {
fireJumpHandler();
}
}
我有接口:
public interface Doable {
void doSomething();
}
和实现它的class:
public class DoJump() implements Doable {
@Override
private void doSomething() {
fireJumpHandler();
}
}
这是一个愚蠢的例子,但我想提出问题。
此代码无法编译,我在 Eclipse 中遇到错误 IDE:
Cannot reduce the visibility of the inherited method from Doable
我有一个声明方法的通用接口。该方法在具体 class 中被重写。我想避免另一个可以扩展这个 class (DoJump
) 的 class,所以我想从 sub classes 中隐藏这个方法。我想使用 private
修饰符,但 Java 不允许我这样做。
为什么不可能,如何解决?
我想回答你的最后一个问题 "How to workaround it?"
,因为相关问题中没有对此进行描述。创建第二个接口 NotDoable
,它根本没有声明 doSomething()
。然后让你的 DoJump
实现这两个接口。给每个不应该覆盖 doSomething
接口 NotDoable
而不是真实类型 DoJump
的引用。然后他们就不会知道该对象确实可以 doSomething
,他们不会知道每个 class 设计。当然,可以解决这个问题,但实际上可以解决所有问题。 class 这样设计更正确。这是一些代码:
public interface Doable {
public void doSomething();
}
public interface NotDoable {
}
public class DoJump implements Doable, NotDoable {
@Override
public void doSomething() {
System.out.println("hi");
}
public NotDoable meAsNotDoable() {
return this;
}
public static void main(String[] args) {
DoJump object = new DoJump();
// This call is possible, no errors
object.doSomething();
NotDoable hidden = object.meAsNotDoable();
// Not possible, compile error, the true type is hidden!
hidden.doSomething();
}
}
但如前所述,可以使用 if (hidden instanceof DoJump) { DoJump trueObject = (DoJump) hidden; }
解决此问题。但是,也可以通过反射访问私有值。
其他 classes 现在实现 NotDoable
而不是扩展 DoJump
。如果你在这个界面声明了其他人应该知道的关于DoJump
的一切,那么他们只能做他们应该做的。您可以调用此接口 IDoJump
和实现 class DoJump
,一个常见的模式。
现在一样,更具体一点。
public interface IDog {
public void bark();
}
public interface ICanFly {
public void fly();
}
public class FlyingDog implements IDog, ICanFly {
@Override
public void bark() {
System.out.println("wuff");
}
@Override
public void fly() {
System.out.println("Whuiiii");
}
public static void main(String[] args) {
FlyingDog flyingDog = new FlyingDog();
// Both works
flyingDog.fly();
flyingDog.bark();
IDog dog = (IDog) flyingDog;
// Same object but does not work, compile error
dog.fly();
ICanFly canFly = (ICanFly) flyingDog;
// Same object but does not work, compile error
canFly.bark();
}
}
现在扩展 class。
public class LoudDog implements IDog {
@Override
public void bark() {
System.out.println("WUUUUFF");
}
// Does not work, compile error as IDog does not declare this method
@Override
public void fly() {
System.out.println("I wanna fly :(");
}
}
最后要注意,如果其他人知道他们的IDog
实际上是一个FlyingDog
(并且他们施放了它),那么他们必须能够呼唤fly()
,因为FlyingDog
必须能飞。此外,它们 必须 能够覆盖行为,只要它们遵循其 method-signature
给出的 fly()
规范。想象一个叫做 PoorFlyingDog
的 subclass
,他需要覆盖默认行为,否则他可以完美地飞行,但他是一个糟糕的飞行者。
总结:向别人隐瞒自己是DoJump
,也隐瞒自己是Doable
,假装只是NotDoable
。或者对于动物,假装只是 IDog
而不是 FlyingDog
或 ICanFly
。如果其他人不作弊(施法),他们将无法对你使用fly()
,尽管你实际上可以飞行。
将 final
添加到 DoJump
声明以防止此 class 被覆盖(因此 doSomething()
也被覆盖)。
public final class DoJump implements Doable {
@Override
public void doSomething() {
fireJumpHandler();
}
}
如果你仍然需要能够继承DoJump
但又不想doSomething()
被覆盖,在方法签名中加上final
修饰符
public class DoJump implements Doable {
@Override
public final void doSomething() {
fireJumpHandler();
}
}