2012-08-05 15 views
5

Por favor, eche un vistazo a la estructura de mi clase. Creo que me gustaría divertirme más con la herencia de lo que es posible.C# - herencia avanzada

En primer lugar hay una clase base abstracta:

public abstract class PolicyDetailed 
{ 
    internal abstract DataContainer GetActiveAsset(); 
} 

A continuación hay otra clase abstracta, que es genérica:

public abstract class PolicyDetailed<T> : PolicyDetailed where T : DataContainer 
{ 
    internal new abstract T GetActiveAsset(); 
} 

Por último hay una clase política específica. AccidentContainer hereda de DataContainer:

public class PolicyAccident : PolicyDetailed<AccidentContainer> 
{ 
    internal override AccidentContainer GetActiveAsset() 
    { 
     return null; 
    } 
} 

Durante la compilación me sale el siguiente error:

'PolicyAccident' does not implement inherited abstract member 'PolicyDetailed.GetActiveAsset()' 

No estoy seguro de lo que los modificadores que debe utilizar para conseguir que funcione. Quizás también deba escribir lo que me gustaría lograr: tengo una colección de objetos de política de diferente tipo (por ejemplo, PolicyAccident, PolicyTravel, etc.) que heredan de PolicyDetailed con diferentes tipos de DataContainer (AccidentContainer, TravelContainer, etc.). Me gustaría llamar al método "GetActiveAsset" en cada uno de ellos sin conocer su tipo específico y hacer referencia a ellos a través de PolicyDetailed. Al mismo tiempo, me gustaría que cada clase devuelva su subclase DataContainer específica. ¿Es eso posible?

+0

¿Es realmente importante para usted declarar que los tipos de contenedor específicos devuelven sus tipos de política específicos? ¡Usted dice que quiere hacer referencia a los objetos devueltos como PolicyDetailed, y de ese modo pierde la información específica de todos modos! (Recuerde que AccidentContainer _IS_ a DataContainer, y AccidentContainer pueden ser devueltos por un método con tipo de retorno DataContainer sin cambiar ninguna firma) – olagjo

+0

Lo necesito en otras partes del código, donde hago referencia al tipo específico de política y uso su contenedor especial. Podría considerar usar dos métodos: uno devolvería un objeto DataContainer, el segundo podría devolver un contenedor específico (pero se siente un poco torpe :() – Rummy

Respuesta

6

El problema es que no puede anular el método no genérico en la misma clase que declara cualquier otro método con la misma firma.

hay algunas opciones:

  • Con mucho, la más simple es dar los dos métodos diferentes nombres. A continuación, puede dar una aplicación en la que sólo PolicyDetailed<T> delegados al nuevo método abstracto:

    public abstract class PolicyDetailed 
    { 
        internal abstract DataContainer GetActiveAsset(); 
    } 
    
    public abstract class PolicyDetailed<T> : PolicyDetailed where T : DataContainer 
    { 
        internal abstract T GetActiveAssetGeneric(); 
    
        internal override DataContainer GetActiveAsset() 
        { 
         return GetActiveAssetGeneric(); 
        } 
    } 
    
    public class PolicyAccident : PolicyDetailed<AccidentContainer> 
    { 
        internal override AccidentContainer GetActiveAssetGeneric() 
        { 
         return null; 
        }  
    } 
    
  • Usted podría introducir otro nivel de la herencia, la introducción de un nuevo nombre de método simplemente para salvar propósitos. Esto es bastante feo:

    public class DataContainer {} 
    public class AccidentContainer : DataContainer{} 
    
    public abstract class PolicyDetailed 
    { 
        internal abstract DataContainer GetActiveAsset(); 
    } 
    
    // This only exists to satisfy the base class abstract member, 
    // but at the same time allowing PolicyDetailed<T> to introduce 
    // a new member with the same name. 
    public abstract class PolicyDetailedBridge<T> : PolicyDetailed 
        where T : DataContainer 
    { 
        protected abstract T GetActiveAssetGeneric(); 
    
        internal override DataContainer GetActiveAsset() 
        { 
         return GetActiveAssetGeneric(); 
        } 
    } 
    
    public abstract class PolicyDetailed<T> : PolicyDetailedBridge<T> 
        where T : DataContainer 
    { 
        protected sealed override T GetActiveAssetGeneric() 
        { 
         // Call the *new* abstract method. Eek! 
         return GetActiveAsset(); 
        } 
    
        internal abstract new T GetActiveAsset(); 
    } 
    
    public class PolicyAccident : PolicyDetailed<AccidentContainer> 
    { 
        internal override AccidentContainer GetActiveAsset() 
        { 
         return null; 
        }    
    } 
    
  • Se podría hacer que la clase no genérica PolicyDetailed una interfaz en su lugar, y el uso de implementación de interfaz explícita para declarar un nuevo método abstracto y todavía implementar la interfaz.