2009-12-02 19 views
11

Derb()メソッドがBaseクラス変数経由で保護されたFooにアクセスできない理由を説明できますか?これは私にとって奇妙に見える:基本クラス変数経由でアクセスされた保護メンバー

public class Base 
{ 
    protected int Foo; 
} 

public class Der : Base 
{ 
    private void B(Base b) { Foo = b.Foo; } // Error: Cannot access protected member 

    private void D(Der d) { Foo = d.Foo; } // OK 
} 

ありがとう!

答えて

22

よくある質問です。なぜこれが違法であるかを理解するには、何が悪くなるか考えてみてください。

Baseから派生した別の派生クラスFrobがあるとします。今度はFrobのインスタンスをDer.Bに渡します。あなたはDer.BからFrob.Fooにアクセスできますか?いいえ、絶対にありません。 Frob.Fooは保護されています。 FrobとFrobのサブクラスからのみアクセス可能にする必要があります。 DerはFrobではなくFrobのサブクラスではないため、Frobの保護されたメンバーにアクセスすることはできません。

ことがはっきりしない場合は、件名に私の記事を参照してください。

http://blogs.msdn.com/ericlippert/archive/2005/11/09/491031.aspx

+0

ありがとうございます。今私にはそれがはっきりしています。 – Roman

0

あなたがしようとしているのは、int Fooに "internal"を使いたい場合です。

+1

これはしませんBが渡されていれば働く。 –

+0

私は保護されているのではなく、社内でも公共でも使用できることを知っています。しかし、保護された理由がポストに記述されているように振る舞っている理由を理解したい。 – Roman

+2

@Roman:protectedはDerivedクラスにのみ表示されるためです。同じインスタンス内。しかし、あなたは別のインスタンスからそれを見ようとしています。もしそれができたら、保護はかなり役に立たないでしょう。 –

4

Bでは、別のクラスの保護されたメンバーにアクセスしようとしています。あなたがそのクラスから継承しているという事実は無関係です。 Dでは、現在のクラスの基本クラスの保護されたメンバーにアクセスしています。このコンテキストでは、Derとそれが継承している型の保護されたメンバーから何かにアクセスできます。

+0

+1については説明していますが、私はまだ「あなたがそのクラスから継承しているという事実は無関係」という理由を疑っていますか?それは仕様述語ですか? – Roman

+0

あなたがそれを継承しているという事実は、誰かがDerを初期化した場合、それにアクセスできるようにします。その場合、それをDerにキャストしてFooにアクセスすることができます。 –

2

簡単に言えば、protectedはサブクラスへのアクセスを許可します。で

private void B(Base b) { Foo = b.Foo; } 

あなたはデルのインスタンスがアクセス権を持っていない保護されたメンバーにアクセスしようとしています。 Der(this)の現在のインスタンスの基本クラスであれば、それにアクセスできます。

private void D(Der d) { Foo = d.Foo; } // OK 

Derクラスを使用しているため、保護された基本クラスのメソッドにアクセスしているため、正常に動作します。

+1

私はあなたが言うことを意味したと思う: 私的空洞D(Der d){Foo = d.Foo; } 正常に動作します。ちょっと混乱させて、コード行を複製してください。 – Doug

+0

Woops、ええ、私は2番目のコードサンプルをコピーするつもりでした。 – Ragepotato

2

あなたは、基本クラスで静的メソッドを宣言することでこの制限を回避することができます

public class Base 
{ 
    protected int Foo; 

    protected static int GetFoo(Base b) 
    { 
     return b.Foo; 
    } 
} 

public class Der : Base 
{ 
    private void B(Base b) { Foo = GetFoo(b); } // OK 
}