2010-02-13 96 views
7

me gustaría lograr esto en C#C# herencia múltiple

(Pseudocódigo)

class A; 

class B : A; 

class C : A, B; 

... 

A ac = (A)c; 

... 

B bc = (B)c; 

Es esto posible?

+0

No, mira esto: http://stackoverflow.com/questions/191691/ http://stackoverflow.com/questions/995255/ –

+0

http://stackoverflow.com/questions/2846752/am-i -trying-to-implementation-multiple-inheritance-how-can-i-do-this y http://stackoverflow.com/questions/2456154/does-c-support-multiple-inheritance – Russell

Respuesta

3

No. C# no admite herencia múltiple de clases.

Una clase puede heredar de una clase y también puede implementar múltiples interfaces.

+0

@stakx: buena captura. Corregido –

0

puede usar interfaces para herencia múltiple.

2

No es posible en C#, pero también debería pensar si este es el escenario que realmente desea.

EsC realmente una A y una B ? O lo hace Ctiene un A y B. Si esto último es cierto, debe usar composición en lugar de herencia.

+0

No puedo usar la composición por alguna razón. Intenté eso. El problema: las clases base usan delegados y proporcionan referencias a sí mismo en la devolución de llamada. Si C incluye A y B, las devoluciones de llamada contienen referencias a A y/o B, no a C según corresponda. Esto está garantizado si heredo C de A y B. Las interfaces son una opción, úsalas ya. – neil

9

No es necesario herencia múltiple en este caso particular: Si la clase C hereda sólo de B, cualquier instancia de la clase C se puede convertir en tanto ByA; desde B ya se deriva de A, C no tiene que ser derivado de A nuevo:

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 

(como ya se ha dicho, si necesita algo parecido a la herencia múltiple, las interfaces de uso, ya que una clase puede implementar tantas de ellas como desee.)

+0

Arggh ... He supervisado lo obvio. ¡Gracias por la pista! Saludos – neil

+0

Hmmm. Queda un problema: no puedo obligar a C a comportarse como A. B mejora a A y ya no proporciona funcionalidades simples A (como se requiere). Simplemente hablado Necesito una C, que a veces se comporta como A y, a veces, como B, según el contexto. – neil

+0

'C' debería comportarse como' A' si accede a través de 'ac'; de forma similar, 'C' debería comportarse como' B' si accede a través de 'bc'. Por supuesto, si tiene métodos virtuales, se invocarán las versiones anuladas en todos estos casos. – stakx

0

C# no es compatible con herencia múltiple, pero como otros han sugerido, puede usar múltiples interfaces en su lugar. Sin embargo, incluso con interfaces a veces se quiere reutilizar implementaciones de múltiples interfaces en la misma clase, lo que de nuevo requeriría herencia múltiple.

Para evitar esto (aunque es casi never needed) he llegado con un enfoque de herencia múltiple simulado usando una combinación de partial classes y T4 Text Templates. Es un ligero truco, pero es mejor que copiar/pegar la misma implementación de interfaz en muchas clases derivadas. A continuación se muestra un ejemplo simplificado:

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 #> 

Es un poco molesto que esto requiere la creación de un archivo tt para cada clase derivada que quiere utilizar la implementación de la interfaz , pero aún guarda en copiar/pegar código si InterfaceImpl.cs es más que unas pocas líneas de código. Probablemente también sea posible crear un solo archivo tt y especificar el nombre de todas las clases parciales derivadas y generar multiple files.

He mencionado este enfoque en una pregunta similar here.