【问题标题】:Why can methods of subclasses be more accessible?为什么子类的方法更容易访问?
【发布时间】:2019-03-11 06:09:50
【问题描述】:

一个简单的例子

class A {
    protected int foo(int x){
        return x;   
    }
}

class B extends A {
    public int foo(int x){
        return x*x; 
    }
}

这在 Java 中是允许的,并且可以正常工作。但是假设在另一个包中你声明了

A b = new B();
int z = b.foo(5);

那么这将不起作用,因为显然 A foo() 是受保护的。但是,为什么首先允许在子类中有更多可访问的方法呢?有没有这样有用的案例?

【问题讨论】:

  • 为什么要禁止?子类的隐私不能真正强制执行:如果你愿意,你可以创建另一个导出值的方法。
  • 这就是简单的 Liskov 替换原则:子类可以更宽容地允许谁调用该方法,因为它至少和超类一样宽容。

标签: java access-modifiers


【解决方案1】:

因为分类应该允许您将子类视为其超类的实例。我认为这被称为is-a 关系(即B is-a A,但不是相反)。我真的不知道有什么好的方法来简洁地解释这一点。

在您的示例中,B 的所有实例也是A 的实例(请注意,这可能过于简单化了,但我认为对于这个示例来说已经足够了)。 A 只保证在自己的定义中拥有公开的方法。 B 恰好创建了一个受保护的方法public,但假设您有另一个名为C 的类没有这样做。好吧,您可以将BC 都转换为A,但是如果您被允许调用A 上的受保护方法,因为B 将其公开,那么当您传递@ 时会出现错误987654334@.

在另一个包中,您将B 转换为A,因此您的对象有效地采用了A 的接口,因此您只能使用A 提供给您的接口。 JVM 能否通过麻烦并注意到 1) A 实际上是 B 并且 2) B 使 foo 公开,所以 foo 应该是可调用的?我的意思是我可以这么想,但是在 JVM 中实现需要付出多少努力,并且容易出错?把事情简单化。如果类型为A,则接口为A。如果类型为B,则接口为A,除此之外B 还包括其他任何内容。

【讨论】:

    【解决方案2】:

    如果您将A 替换为B,您可以编译第二个示例。这就是重点:B 可以在 A 可以使用的任何地方使用,但也可以添加其他功能(例如公开方法)。

    【讨论】:

      【解决方案3】:

      一般来说,子类可以向它们从父类继承的接口添加方法。使方法更易于访问实际上是添加到接口中。

      但是为什么首先允许在子类中有更多可访问的方法呢?

      因为它对于包含子类引用的代码很有用。

      这有什么用处吗?

      一个很好的例子是Object.clone(),一种受保护的方法。所有Java 类都是Object 的直接或间接子类。支持克隆的子类可以选择公开这个方法。

      Foo foo1 = new Foo();
      Foo foo2 = foo1.clone(); // Sometimes you're holding a subclass reference.
      

      【讨论】:

      • 关于clone的一般例子还不错,1+,但一般该方法应该在Cloneable中;在ObjectIMO 中拥有它是一个糟糕的主意
      • @Eugene - 是的,Cloneable 接口肯定应该包含一个 clone() 方法。 [请参阅 Joshua Bloch 的 Effective Java 中的更多讨论:“Override clone judiciously”。] 另外,在支持逐字段复制的某处提供默认实现很有用。受保护的对象成员为子类的可选使用提供了默认实现。无论 Object 方法是否被称为 clone() 或其他名称,子类都可以选择提供公共 clone() 方法。
      • clone() 的设计很糟糕,因为它依赖于子类中 Object.clone() 的扩展访问修饰符。所以我不认为clone() 是一个很好的例子,为什么我们可以使用扩大访问修饰符。恰恰相反:一个很好的例子,为什么我们不应该使用它。
      • @davidxxx - 您在此处和您的回答中都断言了这一点,但并未显示出有害影响。您声称它会导致“仅在运行时失败”的断言似乎并不正确。
      猜你喜欢
      • 2019-03-11
      • 2015-08-14
      • 2014-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-21
      • 1970-01-01
      相关资源
      最近更新 更多