2010-01-30 34 views
9

我明白製作一個類的單個方法的動機sealed/final,但是完全禁止繼承類的服務的目的是什麼?雖然允許重寫某些方法會導致不好的事情發生,但我看不出如何讓純粹從您的類繼承的繼承添加行爲而不覆蓋現有行爲永遠不會是壞事。如果你真的想禁止在你的類中重寫任何東西,爲什麼不直接讓每個方法都是最終的,但仍然允許繼承來添加行爲?你爲什麼要把整個課程封爲/最終?

+0

在java.util.UUID的情況下,我發現無法繼承令人沮喪的類。 – 2014-01-31 01:25:50

回答

3

組織/軟件開發團隊可能希望執行某些編碼標準。例如,爲了提高可讀性,他們可能只希望用方法Z修改類Y的屬性X,而不用其他方法。如果這個類不是最終的,那麼一些開發者可能會擴展Y類並添加方法W,這可能會以不同的方式修改X,並且在理解編寫的代碼時會引起混淆和延遲。

+0

是不是將屬性X私人化爲同一個東西? – Dalius 2013-08-01 20:23:00

+1

@Dalius即使使用X private,也許只需要直接調用Y對象上的Z來影響X.如果類W覆蓋Z,那麼您可以通過調用W對象上的Z來改變X,這打破了通過直接從Y對象直接調用Z方法來改變X的初始願望。我個人從未見過這種情況,但我猜想可能會發生。 – 2014-02-17 14:48:53

4

裏有「爲什麼字符串是最後在Java」的問題,關於這個一些很好的討論:Why is String class declared final in Java?

在這種情況下的基本總結,字符串是不可變的,如果它可以被繼承,子類可能讓它變得可變。

2

想想這樣:你花了3個月時間處理其他人將要使用的框架的基類,並且框架的整體一致性基於此類中編寫的代碼,修改這個類可能會導致你的框架的錯誤,錯誤和不當行爲,你如何防止你的優秀程序員擴展它並覆蓋它的一個方法?

除此之外,還有一些應該是不可變的類,例如Java中的java.lang.String類,擴展它,並改變它的行爲可能會造成很大的混亂!

最後,有時將類或方法設置爲最終會提高性能,但我從來沒有測試過它,並且沒有看到任何理由讓一個類/方法最終獲得等於非常微小的性能增益與在程序中執行其他內容所需的時間相比爲零。

+0

1.問題是允許子類添加行爲。我明白你爲什麼要禁止重寫。如果一個班級需要3個月的時間寫作,那可能太過分了。 – dsimcha 2010-01-30 22:25:29

+0

不要花3個月時間,這個想法是一個重要的階級,在一個脆弱的環境中,每個其他階級都期望它會服從某種行爲。 – 2010-01-30 22:29:00

3

更一般地說,一個類可以做成最終的,以保持使它工作的不變量。我強烈推薦Joshua Bloch的「有效的Java」,以便對此和相關問題進行精彩的討論。

0

我認爲這取決於。

如果我有一個內部應用程序,默認情況下,我不會在課堂上使用最終的級別。代碼太混亂了。在某些情況下,如果我想要安全地重構最終修飾符(甚至非常煩人)(請參閱programming by difference術語)。在某些情況下,當我嘗試重構時,「默認最終狂熱」會造成很大的問題。

另一方面,如果我設計一個api /框架,其中代碼更多的是擴展驅動的,我會使用final來更加激進地進行類。這裏錯誤的擴展可能是一個大問題,'final'修飾符是避免這種編程錯誤的安全方法。

但我只是反對說,像許多人一樣默認使用'final'。它往往有更多的弊端作爲優勢。對我來說,默認設置應該是「明智的和更常見的設置」。

0

據我所知,這是關於保持不變式。

在一個類似的情況,比如,你可以讓你的屬性公開,但隨後你會失去控制自己的價值,因爲客戶將能夠直接改變他們,打破一些你想保持性能。因此,與禁止客戶端直接訪問某些(實際上是)字段以保持某種不變性的方式相同,也可以使您的類/方法最終保持一定的不變。

一個常見的例子我看到有更改的,可如果一個類不是最終被打破的事情。

的問題是不是真的當用戶擴展一個類,並使用它只是在他的系統,與一切隔絕了自己的「爛攤子」的生活。真正的問題與類/方法/屬性/對象/ ...不是孤立存在有關。假設你有一個類CC1的集合,它們向某個目標合作,其中一個類CC1_A應該「產生」只有不可變對象(或者任何其他不變的對象)。然後,繼續並擴展CC1_A,使CC2_AX(在第二個類集合中擴展A)。你現在可以做的是使用CC1的東西通過CC2_AX需要CC1_A。但是,CC1的構建假定CC1_A對象是不可變的,但您的CC2_AX對象不是(假設它們不僅僅是爲了示例)。這可能會導致程序中的嚴重故障。這個問題甚至可能發生在班級內部。例如,CC1_A的方法可能會假定CC1_A對象是不可變的,因此來自CC1_A的CC2_AX方法可能會失敗,因爲CC2_AX會破壞不變性屬性。

在我們的系統,我們今天有很多類,有很多我們做什麼去含蓄。所以我們並不總是想到我們想要維護的不變量。這不會讓事情變得更容易。

順便說一句,一些其他的不變量包括了諸如:

  • 的排序方法應該是穩定的。
  • 的<這樣>方法使用<其它這樣>算法。
  • This <class>列表實現應該使用簡單的鏈表實現,如<一些地方>。

它的推移和。有些類只是因爲它們保持更強的不變量(例如,使用特定算法)纔有用,而擴展則允許人們輕鬆打破這類事情。而這是所有問題的原因都與這些不是孤立生活的事情有關。

相關問題