2009-05-22 54 views
7

讓我們從另一個行爲開始吧:即使您將一個方法/變量聲明爲私有,同一個類的另一個實例也可以訪問它。沒關係,我可以忍受它。我稱這些類爲私有而非實例爲私有。在Java中,爲什麼超類方法不能從子類實例訪問受保護的或私有的方法/變量?

現在問題部分: 例如,在運行時,我希望能夠檢查this類中的所有字符串變量都不爲null,如果它們爲null,則應將其更改爲字符串「NULL」。

我可以使用反射運行變量並獲取它們的值。但是,如果我擴展我的類並添加私有或甚至受保護的變量,則我的基類無法訪問它們。在我可以使用它們之前,我必須對變量setAccessible

所以請向我解釋爲什麼基類(超級類)不能從其子類訪問私有/受保護的變量。這是它的子類,所以我不明白。這背後有什麼想法?

我知道超類不應該知道它的子類,但在我的例子中它是有道理的,不是嗎?

是否因爲我不能或不應該以這種方式限制我的子類?


更新: 基礎上的答案,我想也知道:爲什麼不從視爲違反封裝的同一類訪問另一個實例的私有變量?

+2

不,它沒有任何意義。 – 2009-05-22 19:00:55

回答

7

這很簡單,因爲這是違反封裝。另一個班級不應該能夠接觸到你的班級,即使你把這個班級概括化了,也不能搞亂事情。例如,一輛汽車如何知道一輛汽車?基礎班的全部要點是爲子班提供服務,但是就像過度保護的家長一樣,你建議的內容太多了。

+0

那麼爲什麼從同一個類實例中訪問另一個實例的私有變量不被認爲是對封裝的違反?汽車應該能夠限制寶馬只有輪子而不是翅膀,因爲如果寶馬擁有翅膀,它不是汽車(即使它使用「內部」翅膀) – 2009-05-22 20:23:49

+1

因爲我是班級。你不能在課堂之外做你所說的話,因此封裝是完全的。從該類中您可以修改該類的另一個實例的私有成員。這是如何違反任何事情?我在上課!我可以改變任何與我想要的課程相關的東西,爲什麼不允許它? – 2009-05-22 20:52:21

4

這完全是關於繼承和封裝。

Java的可見性規則指出

  1. 私有成員只能在定義它們在
    • 定義它們
    • 保護的成員只能是訪問類訪問定義它們的類的子類
    • 與定義它們的類在同一個包中的其他類

當然,正如你提到的,在反射就可以改變規則(除非了SecurityManager禁止它)

+1

或者,言簡意賅:此行爲是設計... – 2009-05-22 19:23:28

0

我往往更看它從一個務實和現實的角度來看:

public class Test1 { 
    private int a = 1; 

    public static void main(String s[]) { 
     System.out.println((new Test1()).a); 
     System.out.println((new Test1()).getA()); 
     System.out.println((new Test2()).getA()); 
    } 

    public int getA() { return a; } 
} 

class Test2 extends Test { 
    private int a = 2; 

    public int getA() { return a; } 
} 

你會用什麼語法Test1來訪問私人會員aTest2。當編寫Test1時,Test2可能不存在。

同樣,一個基類(超類)時,它已經從繼承不知道。爲了讓基類知道它何時被繼承,你必須能夠在繼承它時修改基類。你是在暗示我應該以某種方式修改我的本地的ArrayList副本,當我寫:

class MyArrayList extends ArrayList 

我決定到你的計算機上運行我的代碼當天發生的事情,你得到的ArrayList我的修改後的副本,它知道MyArrayList,還是我修改計算機上的副本莫名其妙?

可以將這些問題以某種方式解決?當然。允許它有什麼價值嗎?沒有我能看到的。

7

要回答你的問題的更新(如原來的問題很好地已回答)私人的目的是爲了隱藏實現細節,使這些執行細節不會成爲依賴。這是面向對象編程的基礎 - 封裝確保複雜性通過將不同部分與自己的區域隔離來保持可管理性。

由於該類知道自己的實現 - 它定義它,沒有什麼限制訪問其他情況下獲得的,因爲類實現所有聲明它已經被暴露在所有這些細節的私人情況。

在這種情況下隱藏它實際上會增加複雜性,因爲你將不得不增加一個額外的訪問級別,允許類級別的可見性,而不是實例級別的可見性,而無需實際真正封裝任何進一步的複雜性。

相關問題