2012-08-05 9 views
5

Bitte werfen Sie einen Blick auf meine Klassenstruktur. Ich denke, ich hätte gerne mehr Spaß mit der Vererbung, als es möglich ist.C# - Erweiterte Vererbung

Zuerst gibt es eine Basis abstrakte Klasse ist:

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

Weiter gibt es eine andere abstrakte Klasse ist, die generisch ist:

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

Schließlich gibt es eine spezifische politische Klasse. AccidentContainer erbt von Datacontainer:

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

Beim Übersetzen ich die folgende Fehlermeldung erhalten:

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

Ich bin nicht sicher, welche Modifikatoren ich hier verwenden sollte, um es zu arbeiten. Vielleicht sollte ich auch schreiben, was ich erreichen möchte: Ich habe eine Sammlung von verschiedenen Richtlinien-Objekten (z. B. PolicyAccident, PolicyTravel usw.), die von PolicyDetailed mit verschiedenen Arten von DataContainer (AccidentContainer, TravelContainer usw.) erben. Ich möchte die "GetActiveAsset" -Methode für jeden von ihnen aufrufen, ohne ihren spezifischen Typ zu kennen und sie über PolicyDetailed zu referenzieren. Gleichzeitig möchte ich, dass jede Klasse ihre spezifische Datacontainer-Unterklasse zurückgibt. Ist das möglich?

+0

Ist es wirklich wichtig für Sie zu deklarieren, dass die spezifischen Containertypen ihre spezifischen Richtlinientypen zurückgeben? Sie sagen, dass Sie die zurückgegebenen Objekte als PolicyDetailed referenzieren möchten und auf diese Weise sowieso die spezifischen Informationen verlieren! (Denken Sie daran, dass AccidentContainer _IS_ ein DataContainer und ein AccidentContainer somit von einer Methode mit dem Rückgabetyp DataContainer zurückgegeben werden können, ohne irgendeine Signatur zu ändern) – olagjo

+0

Ich benötige es in anderen Teilen des Codes, wo ich auf bestimmte Policy-Typen referenziere und deren verwende Container. Ich könnte in Betracht ziehen, zwei Methoden zu verwenden - eine würde ein DataContainer-Objekt zurückgeben, die zweite könnte einen bestimmten Container zurückgeben (aber es fühlt sich irgendwie plump an :() – Rummy

Antwort

6

Das Problem besteht darin, dass Sie die nicht generische Methode in derselben Klasse nicht überschreiben können, wenn Sie eine andere Methode mit derselben Signatur deklarieren.

Es gibt ein paar Optionen:

  • Bei weitem die einfachste ist, die beiden Methoden verschiedene Namen zu geben. Dann können Sie eine Implementierung in PolicyDetailed<T> denen nur die Delegierten auf die neue abstrakte Methode geben:

    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; 
        }  
    } 
    
  • Sie könnte vorstellen eine weitere Ebene der Vererbung, eine neue Methode Namen Zwecke nur zur Überbrückung einzuführen. Das ist ziemlich hässlich:

    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; 
        }    
    } 
    
  • Sie könnten die nicht-generischen PolicyDetailed Klasse eine Schnittstelle stattdessen machen und explizite Schnittstellenimplementierung verwenden, um eine neue abstrakte Methode zu erklären, und immer noch die Schnittstelle implementieren.