2012-05-18 108 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是,尽管该类本身只允许本身是白色的,现在红。