変数 - c# 継承 複数




C#はプライベートで保護された継承の概念を持っていますか? (7)

C#は私的/保護された継承の概念を持っていますか?もしそうでなければ、なぜですか?

C ++


class Foo : private Bar {
 public:
   ...
 }; 

C#


public abstract NServlet class : private System.Web.UI.Page
{
    // error "type expected"
}

私は.aspxページに "サーブレットのような"コンセプトを実装しています。具体的なクラスにSystem.Web.UI.Pageベースの内部を見る機能を持たせたくありません。


いいえ、それはありません。 このような制限を許すことのメリットは何ですか?

プライベートおよび保護された継承は、カプセル化(情報隠蔽)に適しています。 Protected *継承はJavaではなく、C ++でもサポートされています。 ここで私のプロジェクトの役に立つ例があります。

第三者フレームワーク**には基本クラスがあります。 それには数十の設定とそれらを操作するためのプロパティとメソッドがあります。 ベースクラスは、個々の設定が割り当てられているときに多くのチェックを行いませんが、受け入れられない組み合わせに遭遇すると、後で例外を生成します。

私はこれらの設定を割り当てるメソッド(例、ファイルから慎重に作られた設定を割り当てる)を持つ子クラスを作成しています。 コードの残りの部分(私の子クラス以外の部分)が個々の設定を操作してそれらを混乱させることを拒否するのは良いことです。

つまり、私はC ++(私的で保護された継承をサポートしています)では、子クラスを親クラスにキャストし、親のpublicメンバーにアクセスできると思います。 ( Chris Karcherの記事も参照してください)それでも、保護された継承は情報の隠蔽を改善します。 クラスB1のメンバーが他のクラスC1およびC2内に真に隠れている必要がある場合、C1およびC2内のクラスB1の保護された変数を作成することによって配列することができます。 B1の保護されたインスタンスは、C1とC2の子ノードで使用できます。 もちろん、このアプローチ自体は、C1とC2との間の多型を提供しない。 しかし、共通のインタフェースI1からC1とC2を継承することで、多態性を追加することができます(必要な場合)。

***簡潔にするために、 "プライベートで保護された"の代わりに "保護された"を使用します。

**私のケースでは、ナショナルインスツルメンツのMeasurement Studio。

  • ニック

@bdukes:メンバーを本当に隠しているわけではないことに注意してください。 例えば:

class Base
{
   public void F() {}
}
class Derived : Base
{
   new private void F() {}
}

Base o = new Derived();
o.F();  // works

編集:しかし、これは、C + +での私的継承と同じ、達成する質問者が欲しいものです:)


NServletクラスがページについて何も知らないようにするには、アダプタパターンの使用方法を調べる必要があります。 NServletクラスのインスタンスをホストするページを作成します。 あなたが何をしているかによって、asp.netのページメンバでAPIを汚染することなく、基本クラスNServletについてしか知りません。


最初の解決策:

保護された内部は、同じアセンブリで公開され、他のアセンブリで保護されます。

継承を介して公開されないクラスの各メンバーのアクセス修飾子を変更する必要があります。

しかし、このソリューションでは、クラスを継承して別のアセンブリで使用する必要があります。 したがって、継承によってのみ使用されるかどうかの選択は、無知な親によって取られます...通常、子供たちはアーキテクチャをもっと知っています...

完璧なソリューションではありませんが、 メソッドを隠すためのインターフェースを追加する代わりに、インターフェースを強制的に使用できない可能性があるため、親クラスのメソッドを子クラスに隠す可能性が残っています。

問題:

プロテクトされたアクセス修飾子とプライベートなアクセス修飾子は、 インタフェース実装しているメソッドには使用できません 。 つまり、保護された内部ソリューションは、インタフェース実装のメソッドには使用できません。 これは大きな制限です。

最終的解決:

メソッドを隠すために私はインタフェースソリューションに落ちました。

問題は、インターフェースを強制的に使用できるようにすることで、隠されるメンバーを常に隠しておいて間違いを絶対に避けることでした。

インターフェイスのみを使用するように強制 するには、コンストラクタを保護、構築 用の静的メソッドを追加します (これをNewと命名しました)。 この静的Newメソッドは、実際にはファクトリ関数であり、インターフェイスを返します 。 だからコードの残りの部分は、インターフェイスだけを使用する必要があります!


いいえ、公開継承のみです。


おそらくServletContainerクラスがNServletの実装で接続されたほうがよいでしょう。 私の本では、私的/保護された継承を許さないことは本当に大事なことではなく、言語をあまり混乱させないようにしています。


私はこれが古い質問だと知っていますが、C#を書く際に何度もこの問題にぶつかりました。

サードパーティのフレームワークのクラスのサブクラスを作成するときにも、パブリックインターフェイスを実装する必要があります。 次に、クライアントにアクセスさせたいメソッドだけを含むようにそのインターフェースを定義します。 次に、クライアントがそのクラスのインスタンスを要求すると、代わりにそのインタフェースのインスタンスを与えます。

これは、これらの種類のことを行うC#の受け入れられた方法のようです。

私が初めてこれをしたのは、C#標準ライブラリに辞書の読み込み専用のバリアントがないことに気付いたときでした。 私はディクショナリへのアクセスを提供したいが、クライアントにディクショナリ内の項目を変更する権限を与えたくない。 そこで、私は、 "Dictionary Dictionary <K、V、IV>:Dictionary <K、V>、IReadOnlyDictionary <K、IV>を定義した。ここで、Vはキータイプ、Vは実数値タイプ、IVは変更を防止するVタイプへのインタフェースです。 DictionaryExの実装はほとんど単純でした。 唯一難しいのはReadOnlyEnumeratorクラスを作成することでしたが、それほど長くはかかりませんでした。

このアプローチで私が見ることができる唯一の欠点は、クライアントがパブリックインターフェイスを関連するサブクラスに動的にキャストしようとする場合です。 これをやめるには、クラスを内部にしてください。 クライアントがパブリックインターフェイスを元の基本クラスにキャストすると、自分たちの生活の中で自分の人生を取っていることは明らかです。 :-)







inheritance