重複の可能性:
C# での多重継承
クラス A とクラス B の 2 つのクラスがあります。これら 2 つのクラスは互いに継承できません。クラス C という新しいクラスを作成しています。今、クラス A とクラス B のメソッドを継承して実装したいと考えています。C# では多重継承ができないことは承知していますが、他にこれを行う方法はありますか?
C#では多重継承はできませんが、インターフェイスを使用してシミュレートできます。C#のシミュレートされた多重継承パターンを参照してください。
B
基本的な考え方は、アクセスしたいクラスのメンバーのインターフェースを定義し(それを呼び出しますIB
)、次に、のインスタンスを内部に格納することによってC
継承A
および実装することです。次に例を示します。IB
B
class C : A, IB
{
private B _b = new B();
// IB members
public void SomeMethod()
{
_b.SomeMethod();
}
}
そのページで説明されている他のいくつかの代替パターンもあります。
継承の一般的な代替手段は委任(コンポジションとも呼ばれます)です。Xは「Y」ではなく「Y」を持っています。したがって、AにFoosを処理する機能があり、BにBarを処理する機能がある場合、両方ともCで、次のようになります。
public class A() {
private FooManager fooManager = new FooManager(); // (or inject, if you have IoC)
public void handleFoo(Foo foo) {
fooManager.handleFoo(foo);
}
}
public class B() {
private BarManager barManager = new BarManager(); // (or inject, if you have IoC)
public void handleBar(Bar bar) {
barManager.handleBar(bar);
}
}
public class C() {
private FooManager fooManager = new FooManager(); // (or inject, if you have IoC)
private BarManager barManager = new BarManager(); // (or inject, if you have IoC)
... etc
}
A
からのメソッドコードを文字通り使用したい場合は、クラスにそれぞれのインスタンスを含めるB
ことができます。C
と のインターフェイスに対してコーディングする場合、クライアントはA
やではなくB
を与えていることを知る必要はありません。C
A
B
interface IA { void SomeMethodOnA(); }
interface IB { void SomeMethodOnB(); }
class A : IA { void SomeMethodOnA() { /* do something */ } }
class B : IB { void SomeMethodOnB() { /* do something */ } }
class C : IA, IB
{
private IA a = new A();
private IB b = new B();
void SomeMethodOnA() { a.SomeMethodOnA(); }
void SomeMethodOnB() { b.SomeMethodOnB(); }
}
構成を使用する:
class ClassC
{
public ClassA A { get; set; }
public ClassB B { get; set; }
public C (ClassA a, ClassB b)
{
this.A = a;
this.B = b;
}
}
次に、を呼び出すことができますC.A.DoA()
。public InterfaceA A
プロパティを、またはのようなインターフェイスまたは抽象クラスに変更することもできますpublic AbstractClassA A
。
2 つのインターフェイスIA
を作成し、次のようにしIB
ます。
public interface IA
{
public void methodA(int value);
}
public interface IB
{
public void methodB(int value);
}
次にA
実装IA
してB
実装しIB
ます。
public class A : IA
{
public int fooA { get; set; }
public void methodA(int value) { fooA = value; }
}
public class B : IB
{
public int fooB { get; set; }
public void methodB(int value) { fooB = value; }
}
次に、次のように C クラスを実装します。
public class C : IA, IB
{
private A _a;
private B _b;
public C(A _a, B _b)
{
this._a = _a;
this._b = _b;
}
public void methodA(int value) { _a.methodA(value); }
public void methodB(int value) { _b.methodB(value); }
}
一般に、これは全体的に貧弱な設計です。なぜなら、と のような同じ名前と変数型を持つメソッドをA
と実装することができ、その実装方法を決定する必要があるか、または との両方を呼び出すだけの場合です。他の場所で提案されているように、2 つのクラスを組み合わせるのではなく、とプロパティを検討する必要があります。B
foo(int bar)
foo(bar)
_a
_b
.A
.B
それらの共通のメソッド/プロパティ/フィールドを保持できる基本クラスを定義できますA
。B
実装後C:Base
。
または、多重継承をシミュレートするには、コモンを定義してinterface
実装します。C
お役に立てれば。
その場合、クラス C を A & B の基本クラスにしたいということですか。
public abstract class C
{
public abstract void Method1();
public abstract void Method2();
}
public class A : C
{
public override void Method1()
{
throw new NotImplementedException();
}
public override void Method2()
{
throw new NotImplementedException();
}
}
public class B : C
{
public override void Method1()
{
throw new NotImplementedException();
}
public override void Method2()
{
throw new NotImplementedException();
}
}