爲什麼子類不能訪問基類的private成員?爲什麼要這樣設計?

  看到很多朋友提問“爲什麼子類不能訪問基類的private成員”?隨後看到很多朋友回答“這是規範”“這是封裝的特性”類似這樣的回答。我覺得大家都是對的。但是有時候您需要關注提問的重點在於why?爲什麼Java要這樣設計private?或者是Object Oriented爲啥要這樣設計這樣的機制?

 

  • 封裝性:首先,private成員具有良好的封裝性(encapsulation)。這個性質對於良好的設計來說是個重要的要素。因爲良好的封裝性會減小耦合的。服務代碼可以定義public函數給客戶代碼。這樣一來客戶代碼可以和服務代碼並行開發。更重要的是,如果修改服務代碼的內部實現也不需要改動客戶代碼。

 

  • 子類也是客戶代碼:對於客戶代碼的理解最直接的就是調用這個類的代碼,這個很好理解。更深入的理解就可以把客戶代碼延伸到這個類的子類。從這一點來說子類就是基類的客戶代碼。你定義了一個class,在裏面寫了些通用的方法,甚至申明瞭abstract方法要求別人來繼承。這個時候基類裏面的protect成員就是對外的API,因爲這些方法對子類來說是可見的,你不能隨意改動。這個時候如果這個成員是public或者protected就可能造成麻煩。對於API來說你不能隨意改動。你能設想JDK裏面的有些類的API改動的情況嗎?至少我會抓狂的:)

 

  • 訪問權限擴大原則:延伸話題來說,還有就是Java對override的時候訪問權限的限制。大家都知道Java的訪問權限從小到大是:private-> default->  protected-> public。如果要override一個基類裏面的方法,那麼子類的這個方法的權限不能比被override的函數權限小。這樣就導致一個隱性的問題:如果你的基類有public方法,那麼它的子類裏面都有這個方法的public屬性。你不能把基類的這個方法private化。換句話說一旦定義了public函數,它的子類都要維護這個public方法。所以就算是方法也要小心地把它設爲public。

 

  當然如果這個基類到最終的子類都是你維護,或者這個類本身就是個非public的類,那麼原則可以放寬。

 

  順便說一下,Eclipse有自動生成標準get/set函數的功能,所以生成get/set是很容易的事情,不要爲了方便把成員都變成public。

 

  譬如寫了個基類Base,然後有人繼承了Base:

 

可是有一天你發覺用ArrayList更好,你就把Base改成:

 

然後所有Base的子類都無法編譯,直接調用到子類data域的類也無法編譯。這就是噩夢,客戶端程序員會用眼光追殺你:)

回過頭來想,如果當初Base的data域是private,由get/set來訪問,那麼你可以輕鬆的修改Base, 子類無需改動:

 作者:盧聲遠<[email protected]>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章