0

私は、次のようなインターフェイスとクラス構造を使用するシステムで作業しています。

interface ILw                // a lightweight interface definition

class Medium : ILw

class FullA : Medium         // full class definitions
class FullB : Medium

class LwA : ILw              // lightweight class definitions
class LwB : ILw

システム内で、完全または軽量の可能性があるオブジェクトに遭遇したため、ILwインターフェイスを必要とする関数があります。この設計で遭遇する問題は、オブジェクトの完全バージョンと軽量バージョンの間で共有する必要があるデータとメソッドが、ILwで定義されているよりも多いことです。だから私は自分が次のようなことをする必要があることに気づきました:

if (myvar is FullA)
{
   (myvar as FullA).MyFunction()
} 
else
{
   (myvar as LwA).MyFunction()
}

ここで、MyFunction()はFullALwAごとに個別に実装され、同一のデータ構造で機能する可能性があります。このコードの重複をなくしたい。

私の C++ バックグラウンドでは、多重継承の典型的なケースのようです。つまり、どちらも必要とするデータとメソッドに対してクラスSharedAを定義し、それをFullALwAの親リストに追加します。しかし、C# とインターフェイスの世界でこれを考えるのに役立つガイダンスが必要です。この問題を解決するために受け入れられたパターンはありますか?

ありがとうございました。

アップデート:

これまでに寄せられたコメントの助けを借りて、1) 共有データの集計を必要とする中間インターフェイスと、2) このデータを操作するメソッドの拡張クラスを使用して、より良い設計にリファクタリングすることができました。理想的には、これら (データとメソッド) は同じ構造に結合されます。mate-in-1 がボード上にあるように感じますが、表示されません。

public interface ILwBase { }

class Medium : ILwBase { }

public class LwDataA
{
    static private int _count = 0;
    public int id;
    public LwDataA() { id = ++_count; }
}

public interface ILwA : ILwBase 
{
   LwDataA ExtData { get; }
}

public static class ExtLwA
{
   public static void MyFunction(this ILwA o) 
   {
      Console.WriteLine("id = " + o.ExtData.id); 
   }
}

class LwA : ILwA
{
   private LwDataA _extData = new LwDataA();
   public LwDataA ExtData { get { return (_extData); } }
}

class FullA : Medium, ILwA
{
   private LwDataA _extData = new LwDataA();
   public LwDataA ExtData { get { return (_extData); } }
}

class Program
{
   static void Main()
   {
      ILwA a1 = new FullA();
      ILwA a2 = new LwA();

      a1.MyFunction();
      a2.MyFunction();
   }
}

これにより、LwA と FullA の間でわずか 2 行の重複コードで必要なものが可能になります。また、集計プロパティ (私の以前の編集) を介して呼び出したり、集計の周りにラッパーを実装したりする必要がなくなります。

うまくいけば、これは私が達成しようとしていることを明確にします。これが最善の解決策ですか?

4

2 に答える 2

2

私たちのコメント交換に続いて、あなたの問題は元の投稿とは異なる観点から見られます. 多重継承によって得られるものを直接持つことはできません。しかし、あなたが非常に近づくことができるさまざまな方法があります。

バリアント 1: 必要な特別なクラスをだましMyFunction()て、拡張メソッドとして受け取るようにします。これを達成するには、「差別化要因」が必要です。私の例では、それは ILwA インターフェイスです。ではなく、別の共通性を定義する必要があることに注意してくださいMyFunction()。ゲッター (またはセッター) で十分です。ここでの制限は、MyFunction がプライベート メンバーにアクセスできないことです。

//instead of the lightweight interface (but use interface if it makes more sense)
abstract class LwBase 

abstract class HwBase : LwBase

public interface IADiff { int APropTrick { get; } }

// lightweight class definitions
class LwA : LwBase, IADiff
class LwB : LwBase

// full class definitions
class FullA : HwBase, IADiff
class FullB : HwBase

public static class AExtensions
{
    public static void MyFunction(this IADiff o)
    {
        // impl.
    }
}

MyFunction()バリアント 2: の実装と「リダイレクト」を提供する共通クラスを使用します。

abstract class LwBase 

abstract class HwBase : LwBase

public interface IADiff { int MyFunction(); }

public class AConcr : IADiff //implemenst Myfunction()

// lightweight class definitions
class LwA : LwBase, IADiff
{
    private AConcr a = new AConcr();

    public int MyFunction() { return a.MyFunction(); }
}
class LwB : LwBase

// full class definitions
class FullA : HwBase, IADiff
{
    private AConcr a = new AConcr();

    public int MyFunction() { return a.MyFunction(); }
}
class FullB : HwBase

バリエーション 3:あなたの質問を調べていたときに、この記事に出くわしました。それが実行可能なオプションかどうかはすぐにはわかりませんが、確かにアイデアが得られます。

クレジット: 私はこの SO スレッドから大量に借りているだけでなく、この素敵なサイトを参照として使用しています。

于 2013-05-09T02:12:02.713 に答える
1

実装を共有するには、両方に から継承させることができますabstract:

interface ILwBase                // a lightweight interface definition
interface ILwA : ILwBase
interface ILwB : ILwBase

class Intermediate : ILwBase

abstract class AbstractA : ILwA {
  void MyFunction() {...}
}

class LwA : AbstractA, Intermediate
class LwB : Intermediate 

class FullA : AbstractA
class FullB : ILwB

抽象クラスの詳細を読む(MSDN)

于 2013-05-09T02:17:50.790 に答える