9

(この質問は、派生クラスの保護されたメンバーにアクセスする C#のフォローアップです)

次のコード スニペットがあります。

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 および protected フィールドは private であり、インスタンスではなく型に対して保護されていることがわかりました。

  • また、アクセス修飾子はコンパイル時に機能する必要があることもわかっています。

  • では、ここで質問です。なぜクラス インスタンスのフィールドにアクセスできないのでしょうか。FurColorFoxRedFox RedFoxから派生しFoxているため、コンパイラは、対応する保護されたフィールドにアクセスできることを認識しています。

  • また、図でわかるように、クラス インスタンスCorrectPaintFoxの保護されたフィールドにアクセスできます。では、クラス インスタンスから同じことを期待できないのはなぜでしょうか。RedFoxFox

4

2 に答える 2

5

単純な理由は次のとおりです。

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

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

内から保護されたフィールドにアクセスしていないBlueFoxため、コンパイラは実行時の型が何であるかを知らないため、常にこれをエラーにする必要があります。

于 2012-05-18T20:19:14.067 に答える
2

受け入れられた答えを少し拡張するために、PHPが持つはるかに緩い意味とは対照的に、コンパイラーがこのルールを適用する理由protectedは、許可したいアクセスを許可すると、クラスの不変条件を破ることができるためです。定義された保護レベルをバイパスすることによって。(もちろん、これは、たとえばReflectionを介して常に可能ですが、コンパイラーは少なくとも偶然に実行することを困難にします)。

問題は、あるオブジェクトがであるということを知っているだけでは、実際には実行時に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クラス自体が白になることだけを許可しているにもかかわらず、私の赤になりました。

于 2012-05-18T20:57:35.137 に答える