我有界面:

public interface Doable {
    void doSomething();
}


和实现它的类:

public class DoJump() implements Doable {
    @Override
    private void doSomething() {
        fireJumpHandler();
    }
}


这是愚蠢的例子,但是我想提出这个问题。

该代码无法编译,我在Eclipse IDE中遇到错误:


  无法降低从继承的方法的可见性
  可行的


我有一个声明方法的通用接口。在具体的类中重写此方法。我想避免使用另一个可以扩展此类(DoJump)的类,因此我想将此方法从子类中隐藏。我想使用private修饰符,但是Java不允许我这样做。

为什么这是不可能的,以及如何解决呢?

最佳答案

我想回答您的最后一个问题"How to workaround it?",因为相关问题未对此进行说明。创建第二个接口NotDoable,它根本没有声明doSomething()。然后,让您的DoJump实现两个接口。给所有不应该覆盖doSomething的人提供对接口NotDoable的引用,而不是真正的类型DoJump。然后他们将不知道对象确实可以doSomething,也不知道每个类的设计。当然,可以解决此问题,但实际上可以解决所有问题。这种方式的班级设计更为正确。这是一些代码:

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; }解决此问题。但是,也可以通过反射来访问私有值。

现在,其他类实现了NotDoable而不是扩展DoJump。如果在此接口中声明其他人应该了解的所有关于DoJump的信息,那么他们只能做应该做的事情。您可以将此接口称为IDoJump和实现类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();
    }
}


现在是扩展类。

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必须可以飞行。此外,只要它们遵循fly()给出的method-signature规范,它们就必须能够覆盖该行为。想象一个名为subclassPoorFlyingDog,他需要改写默认行为,否则他可以完美地飞行,但他的飞行能力很差。

总结:向其他人隐藏您实际上是DoJump,也向您隐藏您是Doable,假装仅是NotDoable。或与动物一起,假装仅为IDog而不是FlyingDogICanFly。如果其他人不作弊(投射),尽管您实际上可以飞行,但他们将无法对您使用fly()

10-04 19:12