2012-01-18 88 views
2

我很困惑爲什麼課程組成了publicprotected方法/變量。 爲什麼只有擴展類可以訪問protected方法/變量?其他人可以幫我指導publicprotected之間的區別和它的功能。公共vs受保護

+2

在其編程語言? – 2012-01-18 11:05:08

+1

你還沒有指定你在說什麼語言 - 而「爲什麼」從根本上可能被回答「因爲這是規範說的」......你應該澄清你的問題。 – 2012-01-18 11:05:16

+1

編程語言無關緊要。公共財產將在課外提供。受保護的財產將不在課堂外提供,但將在兒童課程中提供。與方法一樣,這是OOP編程的一種方式。在谷歌的OOP閱讀更多。 – Slavic 2012-01-18 11:08:14

回答

8

爲什麼只有派生類可以訪問受保護的成員?

因爲這是定義的「保護」。受保護成員的可訪問性域是類及其派生類。

也許你打算問:

爲什麼我總是甚至訪問受保護的成員,當我在派生類中?

這很複雜。有關詳細解釋,請參閱我的六部分系列「爲什麼我不能從派生類訪問受保護的成員?」

http://blogs.msdn.com/b/ericlippert/archive/tags/protected/

1

假設這是在Java語言環境中。

  • public - 可以從任何類
  • protected訪問 - 可以從子/派生類中只有
3

那麼,爲什麼他們這樣做是因爲這只是他們是什麼進行訪問。我想也許你想知道爲什麼要這樣做。簡單的答案是因爲派生類需要訪問它們,而外部類不需要。

訪問修飾符(以及publicprotected,有privateinternalprotected internal)是保持代碼可以理解,儘可能減少錯誤的手段。

有些語言沒有任何形式的封裝。在他們最極端的情況下,任何代碼都可以改變任何數據。有紀律的編碼器會減少給定類型的數據被操縱的位置數量,但它可能仍然不是顯而易見的可能使對象*處於不同狀態的所有操作組合。當他們的代碼被用作別人代碼的一部分時,情況會變得更糟。

訪問修飾符幫助我們處理這個問題。我們默認會員是私人的。然後,成員可以訪問的唯一位置就是類本身。這意味着:

  1. 唯一的錯誤在於如何操縱它們,是在課堂內部。
  2. 唯一需要擔心保持這些成員處於一致狀態的代碼是在類中,並且代碼不必擔心其他代碼可能會使其失敗。
  3. 通過查看一個類的定義(通常在一個文件中並且很少在兩個以上),可以獲得這些字段被操縱的每種方式的完整圖片。

這使我們更容易編碼。

當然,一切都是私人的課程並不是很有用。我們通常不得不讓一些成員公開。通常情況下,我們的領域是私人的,一些有用的方法是私人的,然後一些公共方法和屬性使用這些方法。我們仍然可以通過檢查一個班級來檢查私人成員的所有可能的操作,儘管我們已經開放了向其他班級調用這些班級的成員。因此,這些成員爲我們提供了類內部和外部的代碼之間的接口,這是我們保護類錯誤狀態的邊界,同時爲其他代碼提供有用的功能。

現在應該清楚,我們不公開某些東西,除非需要,但我們確實需要有用的工作才能成爲可能。

讓會員受到保護讓我們處於中間地帶。我們仍然在減少可以操縱的地方,但不是那麼嚴重。通常,這樣做是爲了讓派生類可以將自己的機制提供給基本中定義的常規接口。

使用它的案例較少,因爲通常情況下我們可以將事物保密 - 這更安全 - 或必須公開纔能有用。其中最常見的情況是公共成員提供功能的位置以及受保護的定義方式來實現它。例如,HttpEncoder提供了幾種處理HTML編碼字符串問題的方法,但是有兩種受保護的抽象方法可以派生類重寫以提供幾種不同方法的通用功能。外部類不需要訪問這些類,但派生類可以。

一個實際的例子。假設我們有一個實現INotifyPropertyChanging的基類。這個接口意味着它必須跟蹤處理器,並在屬性即將改變時引發事件。

我們不希望外界班,以提高該事件,因爲這不是他們的業務,並讓他們這樣做僅僅是將導致錯誤。

我們必須讓派生類可以這樣做,因爲它們可以定義基類不知道的屬性。

因此,我們在此基類中定義一個引發事件的受保護方法。外部類不能調用它(降低被錯誤調用的風險),但派生類可以(能夠完成他們需要做的工作)。

*來自面向對象的背景的人甚至可能不會將這些數據視爲「對象」。

2

我也一直在通過publicprotected混淆。

A protected變量(或方法)不能從實例中訪問(使用new創建);它只能從擴展超類的子類訪問(使用extends擴展)。

這類似於Java的例子應該有助於澄清的差異。

// Super-Class: Vehicle 
public class Vehicle { 

    // (1) I'm a protected variable 
    protected String engine = "engine"; 

} 

// Sub-Class: Car 
public class Car extends Vehicle { 

    public String printEngineSuccess() { 
    // (2) We can print a protected variable, 
    // from within this class because it extends 
    // the super-class `Vehicle`. 
    System.out.println(super.engine); // --> SUCCESS 
    } 

    public String printEngineError() { 
    // (3) We can NOT print a protected variable, 
    // from a `new` instance of the super-class `Vehicle`. 
    Vehicle vehicle = new Vehicle(); 
    System.out.println(vehicle.engine); // --> ERROR 
    } 

    public static void main (Strings[] args) { 
    printEngineSuccess(); 
    printEngineError(); 
    } 
}