2012-05-18 107 views
9

(這個問題是一個後續C# accessing protected member in derived classC#保護字段訪問

我有下面的代碼片段:

public class Fox 
{ 
    protected string FurColor; 
    private string furType; 

    public void PaintFox(Fox anotherFox) 
    { 
     anotherFox.FurColor = "Hey!"; 
     anotherFox.furType = "Hey!"; 
    } 
} 

public class RedFox : Fox 
{ 
    public void IncorrectPaintFox(Fox anotherFox) 
    { 
     // This one is inaccessible here and results in a compilation error. 
     anotherFox.FurColor = "Hey!"; 
    } 

    public void CorrectPaintFox(RedFox anotherFox) 
    { 
     // This is perfectly valid. 
     anotherFox.FurColor = "Hey!"; 
    } 
} 
  • 現在,我們知道,private and protected fields are private and protected for type, not instance.

  • 我們也知道訪問修飾符應該在編譯時工作。

  • 所以,這裏是一個問題 - 爲什麼我不能訪問RedFoxFox類實例的FurColor領域?RedFox源自Fox,所以編譯器知道它有權訪問相應的受保護字段。

  • 另外,正如您在CorrectPaintFox中看到的那樣,我可以訪問RedFox類實例的受保護字段。 那麼,爲什麼我不能期望從Fox類實例相同?

+7

有一個[Eric Lippert關於該主題的博客文章](http://blogs.msdn.com/b/ericlippert/archive/2005/11/09/491031.aspx)。 –

+1

爲什麼?因爲這是指定語言的方式:http://msdn.microsoft。com/en-us/library/aa691129(v = vs.71).aspx –

回答

5

原因很簡單:

public void IncorrectPaintFox(Fox anotherFox) 
{ 
    anotherFox = new BlueFox(); 

    // This one is inaccessible here and results in a compilation error. 
    anotherFox.FurColor = "Hey!"; 
} 

現在你不是從BlueFox內訪問受保護的領域,因此,因爲編譯器不知道運行時類型是什麼,它總是使這是一個錯誤。

+0

@Cicada - thanks,updated –

+0

+1人總是忘記兄弟姐妹班... –

2

要在公認的答案稍有擴大,原因編譯器強制執行這個規則,而不是的protected是PHP有更寬鬆的意義,是因爲讓你想允許將有可能給訪問通過繞過其定義的保護級別來打破一個班級的不變量。 (當然,這總是可能的,例如通過反射,但編譯器至少很難做到,意外)。

的問題是,只知道某個對象是Fox並不能使它安全地爲您與它的內部工作交流,因爲它可能不是實際上是一個Fox運行 。考慮到這些類:

public class Fox 
{ 
    protected Color FurColor; 
} 

public class RedFox 
{ 
    public RedFox() 
    { 
    this.FurColor = Color.Red; 
    } 
} 

public class ArcticFox 
{ 
    public ArcticFox() 
    { 
    this.FurColor = Color.White; 
    } 
} 

你所問的是編譯器,可以進行如下方法,假設它在RedFox類中定義:

public void PaintFoxRed (Fox fox) 
{ 
    fox.FurColor = Color.Red; 
} 

但如果這是合法的,我可以做這樣的:

RedFox a = new RedFox(); 
Fox b = new ArcticFox(); 
a.PaintFoxRed(b); 

ArcticFox是,儘管該類本身只允許本身是白色的,現在紅。