2011-01-19 10 views
4
public class _base 
{ 
    protected int x = 5; 
    protected int GetX(_base b) { return b.x; } 
} 


public class _derived : _base 
{ 
    public int Foo() 
    { 
     var b = new _base(); 
     //return b.x; // <-- this would be illegal 
     return GetX(b); // <-- This works and does exactly the same as the line above 
    } 
} 

(コードを変更しないでください。それは働いて、問題を示している。)名前セマンティック

エラーは、bがであるためという

Cannot access protected member '_base.x' via a qualifier of type '_base'; the qualifier must be of type '_derived' (or derived from it) 

注意です_baseとタイプし、私たちはベースにいません。プロテクトされたメンバーにはアクセスできません。なぜなら、_baseは他の派生型なので、コードを保護していない可能性がありますが、それは意味がありません。私がやっていることは、保護された特別な方法を使って上記の問題を回避することです。これは私が望む行動と私が望む保護を私に与えます。私は、このようなアクセスを許可するキーワードがあったと思いますが、そうではありません。私が興味を持っているのは、この "パターン"に名前があるかどうかです。

(私が使用している内部は、同じアセンブリのアクセスで誰でもできますので、保護された)

+0

クラスクラッカーに似ています。 .netには内部スコープもあります。 – Neil

+0

ノートここでやっていることは悪い考えだと思います。このようなニーズを避けるために、クラス階層を設計する方が良い方法があります。 – Neil

+1

これを実現する方法を説明してください!これを可能にするC#にキーワードはありません。内部と友人は多くのアクセスに道を譲ります。保護は十分ではありません。私はクラス内のクラスのインスタンスの保護されたメンバにアクセスしたいので、標準のoopメソッドを使ってクラスを行う方法はないと思います。 (インターフェイスはすべてパブリックアクセスであり、私はそれを回避しようとしています) – AbstractDissonance

答えて

3

アクセス修飾子はクラス(メタアクセス属性として)に作用するため、通常、この種のアクセスは許可されません。派生クラスでは、基本クラスのインスタンスに派生クラスとのクラス関係はありません。ここでは、インスタンスとクラスを混合しています。 protectedキーワードは、派生クラスへのアクセスのみを提供しますが、(たとえ派生クラス内であっても)インスタンスからのアクセスのみを提供します。

明らかにこの言語には欠点がありますが、使用されていない時間の99.9%が必要なわけではありません。いずれにせよ、C#にはあなたが望むものを提供するキーワードはありません。

0

カプセル化。

http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming

基本的には、アクセサ(「セッター」と「ゲッター」)を介してメンバーへのアクセス権を持つユーザーを制御。基礎となるデータのレイアウト方法は、ユーザーには表示されません。この

思う:

あなたのベースクラスに(何らかの理由のために)あなたのX変数の名前を変更したいのですが、それを直接アクセスし、その基本クラスから派生した100クラスが存在する場合。

あなたはそのコードを壊すでしょう。 xが直接アクセスすることはできませんので、

class derived 
{ 
    void DoSomething() { x += 1; } // x renamed, doesn't compile anymore 
} 

さて、カプセル化を使用して、我々はアクセサを得た:

class derived 
{ 
    void DoSomething() { SetX(GetX() + 1); } // No prob! 
} 
+0

彼がもう一度やっていることを読んでください。カプセル化を破る方法のようなものです。 – Neil

+0

私はあまりにも速く読むと思います。 – vdsf

+2

名前の変更には問題はありません。リファクタリングツールを使用して名前を変更すると、Visual Studioは 'x'の使用方法を変更します。また、 'x'の名前を変更して' GetX() 'の名前を変更しようとする可能性もあります。 – SimonC

2

UPDATE:質問が書き換えられているので、この答えを書き換えます。

あなたが示したパターンの名前はわかりません。

あなたが推測しているように、フィールドにアクセスすることが不正な理由は、インスタンスbが_derivedのインスタンスであることがわからないためです。 "保護された"アクセスとは、_derivedが保護されたメンバーにアクセスできることを意味します。_derivedのインスタンス。 _baseから派生した "SomeOtherType"のインスタンスの保護されたメンバーへのアクセスは許可されません。質問が本当にあるならば

さて、「からメンバーxへ直接アクセス任意のインスタンスを通じてすべての派生クラスを取得する方法はありますか?」次にはい。あなたはそれを内部にする明らかな解決策を拒否します。 (*)別の方法があります。 BおよびD1およびD2は、すべての直接this.xにアクセスすることができるが、それ以外の種類の方法がそうすることが可能な派生クラスのメソッドの今

abstract class B 
{ 
    private B() {} 
    private int x; 
    private class D1 : B { } 
    private class D2 : B { } 
    public static B MakeD1() { return new D1(); } 
    public static B MakeD2() { return new D2(); } 
} 

方法:これを行います。 D1とD2以外の派生型はありません。 Bの唯一のコンストラクタは非公開であるため、存在することはできません。抽象的であるため、D1やD2でないBのインスタンスは存在しません。あなたがあなたのメンバーへのアクセスを心配する必要が唯一の人々があなたの同僚あり、それが内部作れば


(*)は、覚えておいてください。彼らがメンバーに嫌なことをした場合、コードレビューで彼らに叩きつけることは、ここではまったく受け入れられる解決策です。

+0

私が投稿した元のコードはC#でうまく動作します。一部の人はそれを変え続ける。アクセスするメンバのインスタンスを渡すために、派生クラスを使用します。それはうまく動作します。 – AbstractDissonance

+0

@abstract - あなたのコードを修正するためにあなたの質問を編集してみませんか?フィードバックが必要な場合は、問題のコードが間違っていても助けにはなりません。 – arcain

+0

ちょっと、D1とD2を持っていても何がポイントですか?私の場合は、実際にはD1とBを公開したいだけでなく、Bをインスタンス化したいと思っています。また、私はクラスのアクセスレベル(彼らはすべて公開されている)について話しているのではなく、それらのクラスのメンバーのアクセスレベルについて話しています。 – AbstractDissonance

0

私はあなたが何を意味していると思いますか?メソッドに基本クラスのインスタンスを作成しないでください。コンストラクタによって作成されます。メンバー名のみを使用するか、大文字と小文字を区別するために、baseキーワードを使用します。

次のようにあなたがそれを使用する上記の例では:

class A : _base { 
    void Foo() { 
     x = 10; //or base.x = 10; 
     SetX(10); //or base.SetX(10); 
     Console.WriteLine(GetX()); //or base.GetX() 
    } 
} 

をさらにあなたはJavaの醜いのgetXとSETXパターンのための素敵な糖衣構文であるProperties構築物に興味があるかもしれません。