【问题标题】:Why a method must be public?为什么方法必须是公开的?
【发布时间】:2014-07-04 20:41:46
【问题描述】:

考虑以下类:

class A {
    void print() {
        System.out.println("A");
    }
}

class B extends A implements C {
}

public interface C {
    void print();

}

我收到此错误:

继承的方法A.print()不能隐藏公共抽象方法 在C

现在,我知道print() 必须公开才能消除编译错误,但这背后的原因是什么?

【问题讨论】:

标签: java oop interface


【解决方案1】:

答案是简单的接口方法总是公开的,或者只是使用组合而不是继承。另请注意,在覆盖方法时,您不能缩小方法的访问级别。

Oracle 文档说:

访问修饰符 public(第 6.6 节)适用于各种接口 声明。

【讨论】:

  • 这是规则,不是原因。
  • @AlanStokes 我在回答中解释了原因,你能检查一下吗?
【解决方案2】:

B#print 永远不可能是真正私有的,因为任何人都可以通过接口调用它:

B b = new B();
C c = b;
c.print();

当它实际上是公开的时,Java 不允许你假装它是私有的。 (C++ 确实如此;不同的语言做出不同的权衡。)

【讨论】:

  • 这不是假装。一方面是控制方法的访问方式,因为在某些情况下这是一个重要方面。
【解决方案3】:

class A 中的方法void print() 是接口方法声明的实现。现在,在interface C 中,这个方法是public(默认每个接口方法都是公共的)并且OOP 规则(特别是Liskov 原则)规定了这个方法在class A 中的实现的可见性不能低于那个在它的界面中 - 因此它必须是public

【讨论】:

  • 我很惊讶没有人提到 Liskov 替换原则。这就是为什么在接口中定义私有方法没有任何意义,以及为什么不允许从派生类中缩小访问修饰符的核心原因。
【解决方案4】:

简短的回答是因为 Java 不允许这样做。根据 9.1.1 下的 Java 语言规范。界面修饰符 - JLS-9.1.1,

访问修饰符 public(第 6.6 节)适用于各种接口声明。

访问修饰符 protected 和 private 仅适用于直接封闭类或枚举声明中的成员接口(第 8.5.1 节)。

因此,如果您未在非成员接口(如 void print())中指定访问修饰符,则它是公共的,实现该接口的类必须提供 public void print()

【讨论】:

  • IOW,它必须是公开的 only 因为规范。这么说?
  • @JensG 如果您所说的规范是指 Java 语言规范,那么是的,因为 Java 的每个实现都应该按照所述规范运行。
  • 所以没有其他的,比如技术上的原因?
  • @JensG 你的意思是,如果不是这样的话,调用者会怎么称呼它?
  • @ElliottFrisch 我认为这是唯一的原因。我不明白为什么规范不允许受保护、封装私有甚至私有接口方法。
【解决方案5】:

好吧,这样想:如果一个接口定义了私有方法,那么这些方法只会被实现该接口的类调用,这并没有太多意义,因为(在 Java ) 一个接口定义了类之间的契约。当一个类跟随一个接口时,接口中定义的方法可以被外部类在实现中调用。

在您的情况下,您的 B 类正在扩展 A,而 A 类没有实现接口 C。因此,通过扩展 A,它继承了一种访问权限低于接口中定义的方法的方法,这是不允许的。

如果您的 A 类实现了接口,您会看到错误“无法降低从 C 继承的方法的可见性”

【讨论】:

  • 如果接口定义了私有方法,那么这些方法将只对与接口相同类中的任何类可见。 class TopLevel { interface Iface { private void dostuff();} class Impl implements IFace { private void doStuff(){}} class User { /* I can call doStuff */ } }
  • 接口不允许定义私有方法。我只是在推测,如果允许他们定义私有方法,可见性的工作方式与您所说的不同。我的代码 sn-p 不应该编译。
  • 啊,你同意我的观点。谢谢。为您的评论 +1。
【解决方案6】:

接口中的所有方法都隐含为public。在您的情况下,方法的名称和返回类型(B 从 A 和 C 继承的方法)相同,但可见性修饰符不同。如果您更改继承方法的可见性修饰符,编译器会报错,因为您无法降低继承成员的可见性

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-29
    • 2011-11-06
    • 1970-01-01
    • 2019-04-03
    • 2011-02-17
    相关资源
    最近更新 更多