52

本当にわかりません。

基本クラスが抽象であり、アセンブリで定義されたパブリックサブクラスに共通の機能を提供するためにのみ使用されることを意図している場合、なぜそれを内部として宣言すべきではないのですか?

抽象クラスをアセンブリの外部のコードに表示したくありません。外部コードにそれを知らせたくありません。

4

5 に答える 5

48

更新:この質問は、2012年11月13日の私のブログの主題でした。この問題に関するいくつかの考えについては、それを参照してください。素晴らしい質問をありがとう!


あなたが正しい; そのようにする必要はありません。他のオブジェクト指向言語では「プライベート継承」が許可されています。これにより、DがBから継承するという事実は、Bを表示する機能を持つコードによってのみ利用できます。

これは、元のC#設計者の設計上の決定でした。残念ながら、私は今机から離れています-長い週末のために数日休みます-それで私は1999年からの言語デザインノートを目の前に持っていません。戻ってきたときにそれを考えたら、それらを閲覧して、この決定の正当性があるかどうかを確認します。

私の個人的な意見では、継承は「一種の」関係を表すために使用されるべきです。つまり、継承は、言語でモデル化されているドメインのセマンティクスを表す必要があります。継承がコード共有メカニズムとして使用される状況を避けようとしています。他の人が述べているように、表現したいのが「このクラスは他のクラスと実装メカニズムを共有する」場合は、継承よりも構成を優先するのがおそらく最善です。

于 2010-09-02T14:24:50.523 に答える
42

クラスから継承することにより、子を介して基本クラスの機能を公開します。

子クラスは親よりも可視性が高いため、保護されているメンバーを公開することになります。

可視性の高い子を実装することで、親クラスの保護レベルに違反することはできません。

基本クラスが実際にパブリックの子クラスで使用されることを意図している場合は、親もパブリックにする必要があります。

もう1つのオプションは、「親」を内部に保持し、非抽象化し、それを使用して子クラスを構成し、インターフェイスを使用してクラスに機能を実装させることです。

public interface ISomething
{
    void HelloWorld();
}

internal class OldParent : ISomething
{
    public void HelloWorld(){ Console.WriteLine("Hello World!"); }
}

public class OldChild : ISomething
{
    OldParent _oldParent = new OldParent();

    public void HelloWorld() { _oldParent.HelloWorld(); }
}
于 2010-09-02T12:16:25.227 に答える
18

あなたができる最も近いことは、MSDNから引用するために、コンストラクターを内部にすることによって、他のアセンブリが抽象クラスを作成するのを防ぐことだと思います。

内部コンストラクターは、抽象クラスが抽象クラスと同じアセンブリにない型の基本クラスとして使用されるのを防ぎます。

次に、EditorBrowsableAttributeをクラスに追加して、IntelliSenseから非表示にしようとするか(正直に言うと、これを使用してさまざまな結果が得られました)、基本クラスをネストされた名前空間に配置MyLibrary.Internalsして、残りのクラスから分離することができます。あなたのクラスの。

于 2010-09-02T13:01:59.297 に答える
4

あなたはここで懸念を混ぜ合わせていると思います、そしてC#は実際に(そしてその前のJava)責任があります。

継承は分類メカニズムとして機能する必要がありますが、コードの再利用によく使用されます。

コードの再利用については、構成が継承よりも優れていることが常に知られています。C#の問題は、次のような簡単な継承方法を提供することです。

class MyClass : MyReusedClass { }

しかし、作曲するためには、自分たちで作曲する必要があります。

class MyClass {
  MyReusedClass _reused;
  // need to expose all the methods from MyReusedClass and delegate to _reused
}

欠落しているのは、トレイト(pdf)のような構造であり、継承と同じユーザビリティレベルに構成をもたらします。

C#(pdf)の特性に関する調査があり、次のようになります。

class MyClass {
  uses { MyTrait; }
}

別のモデル(Perl 6の役割のモデル)を見たいのですが。

アップデート:

ちなみに、Oxygene言語には、インターフェイスのすべてのメンバーを、そのインターフェイスを実装するメンバープロパティに委任できる機能があります。

type
  MyClass = class(IReusable)
  private
    property Reused : IReusable := new MyReusedClass(); readonly;
      implements public IReusable;
  end;

ここでは、のすべてのインターフェイスメンバーIReusableが公開されMyClass、すべてプロパティに委任されReusedます。ただし、このアプローチにはいくつかの問題があります。

別の更新:

この自動構成の概念をC#で実装し始めました。NRolesを見てください。

于 2010-09-08T17:10:51.957 に答える
3

これはリスコフの置換原則に違反すると思います。

このような場合、私は内部クラスを使用し、継承よりも合成を好みます。内部クラスにそのようなすべての機能を含めることを禁止し、パブリッククラスにこの内部クラスのインスタンスを含めることを禁止する設計について何かありますか?

于 2010-09-02T12:35:25.523 に答える