2012-11-26 98 views
2

我正在寫一個代表一些簡單幾何的Java類。爲什麼使用private修飾符來實現不可變的final實例var?

在最上面的abstract類(本身是包私人)我已聲明屬性,我需要從同一包中的子類訪問。

如果我宣佈爲finalAbstractClass屬性,

final int foo; 

我就能夠訪問它直接在包裝,沒有一個getter方法的任何大驚小怪。 但是。根據「實踐」(或什麼,我認爲這是常見的款式)會做:

private final int foo; 

這當然需要一個非private吸氣。子類必須參考foo(這是一個非常相關的,典型的屬性),就好像它是一些外部對象:

this.getFoo(); 

它增加了代碼,並刪除訪問這些成員的直接的方式(即foo)。

是否有跳過private修飾符的缺點,因爲它們無論如何都是最終的,我不擔心在包內部公開這些屬性?

我知道OO倡導者聲稱getters/setters是對象訪問自己屬性的一種非常自然的方式 - 但是什麼時候這會使得任何非美化的,非[插入任何JavaBeans風格的東西], 區別?

考慮一個內部類,Coordinate,它是如此的簡單,因爲它有兩個int屬性 - 使所有使用情況OuterClass類:

class OuterClass{ 
    final static class Coordinate{ 
     final int x, y; 
     Coordinate(int x, int y){ 
      this.x = x; 
      this.y = y; 
     } 
    } 
    Coordinate coordinate; 
} 

對於這個內部類 - 爲什麼我要與創建的實踐打擾一個吸氣? 一個吸氣器會引入更多的代碼,並強制任何一個類在同一個包中調用coordinate.getX();而不是簡單的coordinate.x;。這裏有什麼開銷?請注意類Coordinate上的final修飾符。

+3

有一些人誰得到所有的熱,如果你允許對象外的對象的字段的任何訪問打擾。對這些人來說,這是有所作爲的。對其他人而言,不。 –

+0

@HotLicks:這實際上是我最大的擔憂:) atm對於我的實現來說當然沒有意義。但我也渴望根據所有偉大的編碼員實踐進行編碼。 我的意思是,因爲它是FINAL,所以只能在查看變量時訪問(package-private),而不是使用getter - 這怎麼會是錯誤的?特別是當直接看時產生更少的醜陋感覺。 – tortal

+0

有一個擔心,如果類的內部隨着時間的推移發生變化,可能需要刪除直接訪問並使用訪問方法。在某些情況下(例如廣泛使用的應用程序的主要公共接口),這是一個現實的問題,但在大多數情況下很少關注。直接方法的簡單性(因此更少的錯誤)可能輕而易舉地超過該關注點。 –

回答

6

getters的優點是將接口從實現中解耦出來。今天,您的getFoo可能不會做任何事情,但會返回foo,但將來您可能想要遠程foo成員,並返回計算結果。一個吸氣器可以讓你做到這一點,而不需要在每個呼叫站點進行更改。

+1

事情是這些變量的生態系統被包含在最終方法和最終變量的隔離中 - 使得任何改變都與現在沒有用的變化不同 因此,如果沒有進一步的需要以任何方式修改如何計算var,那麼沒有理由? (某種程度上,如果你要求getX,並且你知道X是最終的,那麼沒有什麼比X本身更值得期待的了......) – tortal

+0

封裝點並不能防止未經授權的更改(這實際上可以是通過標記最終成員來實現)作爲從界面去耦合的細節。如果你不關心這一點,那麼沒有其他原因。 –

+0

特別是如果這是一個學習練習,你應該接受封裝範例,並確保你完全理解你爲什麼使用getter和setter這樣的技術 - 而不是偷工減料,因爲這是一個「真正簡單」的項目。學習練習的目的是模擬真實世界中的問題,這些問題不像您在課堂上可以解決的問題那麼簡單,但可以使用相同的方法進行處理。 –

2

如果您打算從JSF Page訪問此值,它將會期望getFoo而不僅僅是foo(即使您編寫了object.foo)。

除此之外,今天這個領域是最後的,從現在開始它可以改變(我猜)。即使這個機會非常接近0,我相信在遵循良好實踐的過程中不會有任何矯枉過正。絕大多數情況下,您正在進行更改,而不是從頭開始編寫代碼,所以儘可能保護自己會更好(如果只需寫入private以及日蝕約4次點擊即可自動生成getter和setter)。

+0

thx爲輸入和好的提及互操作性的關注,真的沒有想到。 – tortal

+0

在我開始使用JSF和Java EE之前,我從未想過他們。要預測如何使用您編寫的代碼(如果它不僅僅是一個愛好項目)真的很難。此外,如果您正在與其他程序員合作,他們可能會期望遵循這些做法。其中一些人開始寫作,在他們的IDE中尋找變數。如果你的公共變量不存在,它可以被忽略。編寫對所有與你合作的人都很友善的代碼也很重要。 – bjedrzejewski

+0

好點。再次感謝。 – tortal

0

爲了延長Feldgendler的回答(用信息這可能是有人需要這個問題的答案非常有用---我認爲這是相關的,因爲它確實是一個關於封裝的問題):

在使用private的效果修飾符,你將不得不創建「​​getter」(例如int getX(){ ... })以維持訪問。這可以在實施的interface中聲明。 Java interface確實而不是允許聲明實例變量,例如final int x;的示例---或任何其他缺少static修飾符的變量。該接口將作爲任何實施類將具有的行爲的聲明。

如果等來實現:

Coordinate implements ICoordinate { ... } 

它可以在許多情況下是有用的:

使用的接口API的

  • 自文檔。
    • 易於閱讀,記錄和管理。
    • 因此,允許多個實現易於使用和交換。
    • 在基於組件的設計和更:提供明確的手段來提供 需要描述的行爲,而不必實際執行任何準備代碼。
      • 示例:然後可以創建提供接口的數據庫組件。 John Doe想寫一個將來會使用數據庫的程序。但是現在,使用其他一些更簡單的存儲形式就足夠了。爲了不重新編寫什麼時候已經工作的代碼,約翰可以實現一個接口(可能被命名爲interface IDatabase)與方法void insert(...); Object get(...);,也許還有幾個 - 然後實現他的臨時解決方案。一天來,他現在有一個數據庫實施相同的interface IDatabase。要交換到新的數據庫,他可能只需要更改*一行代碼*(例如構造函數調用)!
  • 爲它着想的一個例子:http://pastebin.com/vvV2Nck8

使用private修飾符

  • ,淨化類的意圖!很像接口,它具有自我記錄的性質。 (它在安全上沒有任何價值)
    • private修飾符意味着它不會被訪問超出範圍。或者等價地 - 只能在一定範圍內訪問。當然也適用於public,「package-private」(無修飾符意味着package-private)和protected
    • 訪問屬性不會明確告訴調用者它是什麼類型的變量。然而,有一個吸氣但沒有設置者說另外的東西...
    • 注意:對於常量(例如static final double LIGHT_SPEED),有合理的理由省略吸氣劑,並讓它代替public。這只是一個慣例,因爲它將清楚什麼是常數,什麼是它自己的成員的對象。
    • 注意2:如果感興趣,請閱讀關於final關鍵字及其對優化的影響。它們可以用於方法以及屬性。 (Does use of final keyword in Java improve the performance?就是一個例子)
相關問題