web-dev-qa-db-ja.com

構成を通じてインターフェースを実装するクラスのボイラープレートを削減する

クラスがあります:ABC、およびDのいくつかの小さいクラスを組み合わせたB

CD、およびIBは、それぞれICID、およびAインターフェースを実装します。

BCDおよびAのすべての機能をサポートしているため、IBICIDおよびAも実装しますが、残念ながらAの実装では多くの再ルーティングが発生します

そのようです:

interface IB
{
    int Foo {get;}
}

public class B : IB
{
    public int Foo {get {return 5;}}
}

interface IC
{
    void Bar();
}

public class C : IC
{
    public void Bar()
    {
    }
}

interface ID
{
    string Bash{get; set;}
}

public class D: ID
{
    public string Bash {get;set;}
}

class A : IB, IC, ID
{
    private B b = new B();
    private C c = new C();
    private D d = new D();

    public int Foo {get {return b.Foo}}

    public A(string bash)
    {
        Bash = bash;
    }

    public void Bar()
    {
        c.Bar();
    }

    public string Bash
    {
         get {return d.Bash;}
         set {d.Bash = value;}
    }
}

Bでこのボイラープレートリダイレクトを削除する方法はありますか? CDAはすべて異なるが一般的な機能を実装しており、IBICIDAを実装しているのは気に入っています。

10
Nick Udell

あなたが探しているものは一般に mixins と呼ばれています。悲しいことに、C#はそれらをネイティブにサポートしていません。

onetwothree など、いくつかの回避策があります。

私は本当に最後のものが本当に好きです。自動生成された部分クラスを使用してボイラープレートを生成するという考えは、おそらく実際に良い解決策を得ることができる最も近いものです。

[pMixins]は、pMixin属性で装飾された部分クラスのソリューションをスキャンするVisual Studioプラグインです。クラスを部分的にマークすると、[pMixins]は分離コードファイルを作成し、クラスにメンバーを追加できます

7
Euphoric

コード自体のボイラープレートは削減されませんが、Visual Studio 2015には、ボイラープレートを自動的に生成するリファクタリングオプションが付属しています。

これを使用するには、まずインターフェースIExampleと実装Exampleを作成します。次に、新しいクラスCompositeを作成し、IExampleを継承させますが、インターフェースは実装しません。

タイプExampleのプロパティまたはフィールドをCompositeクラスに追加し、IExampleクラスファイルのトークンCompositeでクイックアクションメニューを開き、 「「例」を介してインターフェイスを実装する」この場合の「例」は、フィールドまたはプロパティの名前です。

Visual Studioはインターフェイスで定義されたすべてのメソッドとプロパティを生成してこのヘルパークラスにリダイレクトしますが、この回答が投稿された時点でnotイベントをリダイレクトすることに注意してください。

2
Nick Udell

クラスの処理が多すぎるため、多くのボイラープレートを実装する必要があります。あなたはコメントで言う:

person.WalkHelper.Walk()とは対照的に、Person.Walk()を書く方が賢明に感じられます。

同意しません。歩く行為には多くのルールが含まれる可能性が高く、Personクラスには属しません。PersonがWalkingServiceを実装するwalk(IWalkable)メソッドを持つIWalkableクラスに属します。

コードを記述するときは、SOLID=の原則を常に念頭に置いてください。ここで最も当てはまるのは、懸念の分離(ウォーキングコードを別のクラスに抽出する)とインターフェイス分離(分割インターフェイス)です。特定のタスク/関数/機能に組み込まれています。複数のインターフェイスを持つIの一部が含まれているように見えるかもしれませんが、1つのクラスにそれらを実装させることで、すべての優れた作業を取り消しています。

1

あなたが探しているのは多重継承です。ただし、C#もJava=もありません。

AからBを拡張できます。これにより、Bのプライベートフィールドとリダイレクトグルーの必要がなくなります。ただし、これはB、C、またはDのいずれかに対してのみ実行できます。

ここで、CをBから継承し、DをCから継承できる場合は、AにDを拡張するだけで十分です。それのための。

C++では、AにB、C、およびDから継承させることができます。

しかし、多重継承はプログラムを推論することを難しくし、それ自体に問題があります。さらに、それを避けるための明確な方法がしばしばあります。それでも、それがない場合もあるので、繰り返しボイラープレートとオブジェクトモデルがどのように公開されるかの間で設計のトレードオフを行う必要があります。

構成と継承を混在させようとしているように感じます。これがC++の場合、純粋な継承ソリューションを使用できます。しかし、それは私が作曲を受け入れることをお勧めしませんので。

0
Erik Eidt