簡體   English   中英

為什么我們不能用私有擴展類方法覆蓋基類方法?

[英]Why can’t we override a base class method with private extended class method?

class One {
    void foo() { }
}
class Two extends One {
    private void foo() { /* more code here */ }
}

為什么上面的代碼片段是錯誤的?

我將嘗試結合其他答案中的想法來得出一個答案。

首先,讓我們看看代碼中發生了什么。

看一下代碼

One類有一個包私有的foo方法:

class One {
    // The lack of an access modifier means the method is package-private.
    void foo() { }
}

Two類是One類的子類, foo方法被覆蓋,但具有訪問修飾符private

class Two extends One {
    // The "private" modifier is added in this class.
    private void foo() { /* more code here */ }
}

問題

Java 語言不允許子類降低子類中方法、字段或類的可見性,因此,降低foo方法可見性的Two類是不合法的。

為什么降低能見度是一個問題?

考慮我們要使用One類的情況:

class AnotherClass {
  public void someMethod() {
     One obj = new One();
     obj.foo();  // This is perfectly valid.
  }
}

在這里,在One實例上調用foo方法是有效的。 (假設AnotherClass類與One類在同一個包中。)

現在,如果我們要實例化Two對象並將其放在One類型的obj變量中呢?

class AnotherClass {
  public void someMethod() {
     One obj = new Two();
     obj.foo();  // Wait a second, here...
  }
}

Two.foo方法是私有的,但是One.foo方法允許訪問該方法。 我們這里有問題。

因此,在考慮繼承時允許降低可見性沒有多大意義。

鏈接

這段代碼的問題在於,如果它是合法的,那么如果您通過One基類間接訪問它,Java 將無法尊重fooprivate修飾符。 例如,如果我要寫

One obj = new Two();
obj.foo();

然后我們會遇到麻煩,因為我們將間接調用Twoprivate方法foo ,因為當編譯器檢查obj.foo()它會查看One以確定foo是否可訪問,而不是在Two 這樣做的原因是編譯器不能總是告訴obj可能指向什么 - 例如,如果我寫了類似的東西

One obj = Math.random() < 0.5? new One() : new Two();
obj.foo();

那么編譯器就無法知道obj指向One還是指向Two 因此,它在檢查訪問說明符時遵循One 如果我們確實被允許在Two標記foo private ,那么編譯器會錯誤地允許我們通過obj調用它,它的類型為One ,繞過只有對象本身可以調用private方法的保證。

給出的答案為您提供了為什么不能一一擴展的技術解釋。 我想讓你理解為什么這是不可能的,因為面向對象模式而不是因為語言本身。

通常,類 One 是一個類的一般定義,它帶有外部世界的訪問器、方法。 擴展此類的子類必須為外部世界提供相同的訪問器。 在您的示例中,兩個擴展了一個,這意味着兩個為外部世界提供了與 One 相同的訪問器。 如果您要更改 One 訪問器的可見性,外部世界將無法再訪問您的類,因為它們習慣於對類型為 One 的對象進行訪問。

它會破壞多態性。

如果你有一個 Two 實例存儲在 Two 變量中,那么不能調用 foo 是有道理的。 但是,如果將 Two 實例存儲在 One 變量中,則您只知道 One。 但是 One 有一個公共 foo,可以調用它。 這將是不一致的,並且真的很奇怪。

因為繼承是一種關系。 任何人都可以通過引用One來引用Two的實例:

One v = new Two();

如果你在 v 引用上調用 foo 方法,程序會做什么? 你破壞了 One 的公共契約,它保證 One 的每個實例都有一個(這里是包保護的)foo 方法。 這就是編譯器禁止它的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM