1. 程式人生 > 其它 >為什麼子類不能訪問基類的private成員?為什麼要這樣設計?

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

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

#為什麼子類不能訪問基類的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:

public class Base {  
	public String[] data;  
}  
class Sub extends Base{  
	public void show(){  
	    System.out.println(Arrays.toString(this.getData()));  
	}  
}  

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

public class Base {  
   //public String[] data;  
   public ArrayList data;  
}

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

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

public class Base {  
    //private String[] data;  
    private ArrayList<String> data;  

    public String[] getData() {  
        return  (String[]) data.toArray();  
    }  

    public void setData(String[] data) {  
        this.data = new ArrayList<String>(Arrays.asList(data));  
    }  
}  

作者:盧聲遠[email protected]

原文

轉載於:https://my.oschina.net/neumeng/blog/677001