2010-02-13 11 views
7

chciałbym osiągnąć to w C#C# wielokrotne dziedziczenie

(Pseudokod)

class A; 

class B : A; 

class C : A, B; 

... 

A ac = (A)c; 

... 

B bc = (B)c; 

Czy to możliwe?

+0

Nie, sprawdź te: http://stackoverflow.com/questions/191691/ http://stackoverflow.com/questions/995255/ –

+0

http://stackoverflow.com/questions/2846752/am-i -wybieranie-do-wdrożenia-wiele-dziedziczenie-jak-można-zrobić-to i http://stackoverflow.com/questions/2456154/does-c-support-multiple-initance – Russell

Odpowiedz

3

Nie. C# nie obsługuje dziedziczenia wielu klas.

Klasa może dziedziczyć z jednej klasy i może również implementować wiele interfejsów.

+0

@stakx: dobry połów. Poprawione. –

0

można używać interfejsów do dziedziczenia wielokrotnego.

2

Nie jest to możliwe w języku C#, ale powinieneś także pomyśleć, czy jest to naprawdę potrzebny scenariusz.

CzyC naprawdę i B? Lub ma , który można dołączyć do komputera użytkownika. Jeśli ta ostatnia jest prawdziwa, powinieneś użyć kompozycji zamiast dziedziczenia.

+0

Nie mogę użyć kompozycji z pewnych powodów. Próbowałem tego. Problem: klasy bazowe używają delegatów i udostępniają odwołania do siebie w wywołaniu zwrotnym. Jeśli C zawiera A i B, wywołania zwrotne zawierają odniesienia do A i/lub B, a nie do C, jeśli jest to wymagane. Jest to zapewnione, jeśli odziedziczę C z A i B. Interfejsy są opcją, użyj go już. – neil

9

Nie trzeba wielokrotne dziedziczenie w tym konkretnym przypadku: Jeżeli klasa C dziedziczy tylko z B, każda instancja klasy C mogą być oddane zarówno BiA; od B już wywodzi A, C nie musi pochodzić z A ponownie:

class A  { ... } 

class B : A { ... } 

class C : B { ... } 

... 

C c = new C(); 
B bc = (B)c; // <-- will work just fine without multiple inheritance 
A ac = (A)c; // <-- ditto 

(Jak inni już powiedziałem, jeśli trzeba coś w rodzaju wielokrotne dziedziczenie, interfejsy użyciu, ponieważ klasa może implementować tyle ile chcesz.)

+0

Arggh ... Nadzorowałem oczywistość. Dzięki za podpowiedź! Pozdrawiam – neil

+0

Hmmm. Pozostaje jeden problem: nie potrafię zmusić C, by zachowywał się tak, jak A. B wzmacnia A i nie zapewnia już prostych funkcji (w razie potrzeby). Mówiąc po prostu potrzebuję C, który czasami zachowuje się jak A, a czasami jako B, w zależności od kontekstu. – neil

+0

'C' powinno zachowywać się jak' A', jeśli uzyskasz do niego dostęp poprzez 'ac'; podobnie, 'C' powinno zachowywać się jak' B', jeśli masz do niego dostęp przez 'bc'. Oczywiście, jeśli masz metody wirtualne, nadpisane wersje będą wywoływane we wszystkich tych przypadkach. – stakx

0

C# nie obsługuje dziedziczenia wielokrotnego, ale inni sugerują, że możesz używać wielu interfejsów. Jednak nawet w przypadku interfejsów czasami konieczne jest ponowne wykorzystanie implementacji wielu interfejsów w tej samej klasie, co ponownie wymagałoby wielokrotnego dziedziczenia.

Aby obejść ten problem (mimo że jest to prawie never needed), wymyśliłem symulowane podejście wielokrotnego dziedziczenia przy użyciu kombinacji partial classes i T4 Text Templates. To drobny hack, ale jest lepszy niż kopiowanie/wklejanie tej samej implementacji interfejsu w wielu klasach pochodnych. Poniżej przedstawiono uproszczony przykład:

IInterface.cs

public interface IInterface 
{ 
    void Foo(); 
} 

InterfaceImpl.cs

public partial class InterfaceImpl : IInterface 
{ 
    public void Foo() 
    { 
     Console.WriteLine("Foo"); 
    } 
} 

BaseClass.cs

using System; 

public class BaseClass 
{ 
    public void Bar() 
    { 
     Console.WriteLine("Bar"); 
    } 
} 

DerivedClassA.cs

public partial class DerivedClassA : BaseClass, IInterface 
{ 
    public void FooBar() 
    { 
     this.Foo(); 
     this.Bar(); 
    } 
} 

DerivedClassAInterfaceImpl.tt

<#@ template debug="false" hostspecific="true" language="C#" #> 
<#@ output extension=".cs" #> 
<# var codeText = System.IO.File.ReadAllText(this.Host.ResolvePath("InterfaceImpl.cs")).Replace("InterfaceImpl", "DerivedClassA"); #> 
<#= codeText #> 

DerivedClassB.cs

public partial class DerivedClassB : BaseClass, IInterface 
    { 
     public void BarFoo() 
     { 
      this.Bar(); 
      this.Foo(); 
     } 
    } 

DerivedClassBInterfaceImpl.tt

<#@ template debug="false" hostspecific="true" language="C#" #> 
<#@ output extension=".cs" #> 
<# var codeText = System.IO.File.ReadAllText(this.Host.ResolvePath("InterfaceImpl.cs")).Replace("InterfaceImpl", "DerivedClassB"); #> 
<#= codeText #> 

To trochę irytujące, że wymaga to tworzenia pliku tt dla każdej klasy pochodnej, która chce wykorzystać wdrożenie interfejsu , ale nadal zapisuje kod kopiowania/wklejania, jeśli InterfaceImpl.cs to więcej niż kilka linii kodu. Możliwe jest również utworzenie tylko jednego pliku tt i podanie nazwy wszystkich pochodnych klas częściowych oraz wygenerowanie multiple files.

Wymieniłem to podejście w podobnym pytaniu here.

Powiązane problemy