簡體   English   中英

類、接口和實現接口的類中方法的覆蓋、重新聲明、隱藏和重新定義

[英]Overriding, redeclaring, hiding and redefining of methods in classes, interfaces and classes implementing interfaces

Would it be correct to say that static methods in a class extended with a class, in an interface extended with an interface and in an interface implemented by a class can only be redeclared in the extending/implementing part (hiding the original method), and任何其他方法只能在那里被覆蓋? 重新定義與覆蓋相同嗎?

如果沒有,有人可以用流程圖解釋這些概念嗎(我看過其他解釋,他們沒有給我我正在尋找的概述)?

說 static 方法在 class 擴展中是否正確

No. static 方法基本上是不可繼承的,不可覆蓋的。 或者更確切地說,從概念上講,它只是不適用。

說:“這個 static 方法是一種替代方法”有點像說:“這聞起來很藍”——甚至不清楚這意味着什么。

覆蓋本質上只與動態調度的概念有關。 動態調度是這樣的想法:

class Dog {
  void bark() { System.out.println("Woof"); }
}

class Bulldog extends Dog {
  void bark() { System.out.println("Grrrr"); }
}

Dog d = new Bulldog();
d.bark(); // prints "Grrrr"

這就是工作中的動態調度。 d是一個變量。 像 java 中的所有非基元一樣,它是一個參考 意思是,存儲在此變量中的值是引用- 一個指針。 地址簿中的地址,可讓您到達房子,而不是房子本身。 d的類型是Dog 它的值是對某些 object 的實際實例的引用(並且 java 保證無論它是一個實例的實際類型,該類型是DogDog的子類型)。 該引用為您提供了Bulldog的實例。 那么,在這里調用bark()時,會發生什么?

動態調度:Java 找到該方法最具體的實現,並調用. 這樣打印Grrrr ,而不是Woof

然而,當談到 static 方法時,整個概念並不適用。 發生動態調度是因為引用的類型(這里是Dog ,即變量d的類型)和引用指向的事物的類型(即Bulldog )之間存在差異。 覆蓋作為一個概念存在是因為這兩種類型可能不同。

調用 static 方法時,這不會出現 你總是寫SomeType.someStaticMethod() ,那么動態調度甚至是什么?

旁注:您可以使用表達式合法地調用 static 方法。 這是合法的:

List.of("a", "b"); // this is how you normally do it
List<Integer> list = new ArrayList<Integer>();
list.of("a", "b"); // this compiles and works

但不要搞錯 - 編譯器對待它是一樣的,關心list的類型,而不關心變量指向的 object 。 事實上, list = null; list.of("a", "b"); list = null; list.of("a", "b"); 工作正常,沒有 NullPointerException,證明這樣做時list不會被取消引用。 所有風格指南都強烈建議不要這樣做,這是有充分理由的。

旁注2:不幸的是,java 允許您將 static 方法聲明為final ,這很奇怪: final意味着:不能被覆蓋,我們剛剛發現“覆蓋”在概念上對 ZA821259CEF456E959 方法沒有意義。 就是這樣 - 這是原始 java 規范和 java 中的設計錯誤,除非有非常好的理由這樣做,否則不喜歡進行破壞現有代碼的更改,雖然這個規范很煩人,但它不會傷害很多。 只是不要將您的 static 方法聲明為final 它甚至添加了一個更奇怪的規則(子類型不能聲明具有相同簽名的 static 方法)。 再次,無視這一點 - java 規范錯誤沒有得到修復,因為不值得頭疼。

重新定義與覆蓋相同嗎?

是的。 2個詞代表同一件事。 正確的術語是“覆蓋”——java 語言規范都使用這個術語,社區中的絕大多數人都這樣做。 如果我是任何教程、博客文章、文檔或演示文稿的編輯,你會得到這個“重新定義”的術語,我會編輯它。 除非作者特意講這個:

class Parent {
  static void foo() {}
}

class Child extends Parent {
  static void foo() {}
}

在這種情況下,“覆蓋”是使用錯誤的術語(鑒於 static 方法和覆蓋是正交概念),盡管我也不會使用“重新定義”。 您只是在一個 class 中定義了一個名為foo的方法,還在另一個 class 中定義了一個名為foo的方法。 一個是另一個孩子的事實是無關緊要的。 現在兩者都有一個foo方法。 child 中的 foo 方法不會覆蓋或重新定義任何東西; static世界中沒有這樣的東西。

有流程圖

流程圖需要某種流程圖來繪制。 由此得名。 這里沒有這樣的東西。

暫無
暫無

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

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