2009-07-31 15 views
1

Ich bin mir nicht sicher, ob es wirklich eine „Polymorphismus“ Frage, aber trotzdem ... So habe ich eine abstrakte Klasse und zwei andere Klassen, die von ihm erben.C# Grund Polymorphismus Frage

aus der Code der Basisklasse hat eine Variable, die unterschiedlich zwischen den Klassen sein würden, die die Basisklasse erweitert.

Was ist der beste Weg, das zu tun? Überschreiben Sie eine "get" -Methode? Ändere die Architektur etwas, um eine Funktion von der Basisklasse zu der erweiterten Klasse aufzurufen, die den Wert übergibt ...

Hier ist ein Beispiel (es wird nicht kompiliert, nur ein kleines Beispiel, wie ich es gemacht habe):

Das ist, wie ich es tat, aber es fühlt sich nicht wirklich klar und einfach IMO zu pflegen.

Jede Idee oder Kommentar willkommen!

+0

durch die Art und Weise, die Basisklassen auch andere Methoden zu implementieren ... –

Antwort

7

ich wahrscheinlich für so etwas entscheiden würde:

public abstract class Base 
{ 
    protected abstract string ListName { get; } 
    public List<Item> GetItems() 
    { 
     return Web.GetList(ListName); 
    } 
} 

public class Child : Base 
{ 
    protected override string ListName 
    { 
     get { return "MyListName"; } 
    } 
} 
+0

Ich denke, es ist der beste Weg, weil es einfacher zu pflegen und einfach ist. Wie gesagt, es ist nicht der beste Weg, es zu tun, wenn es nur das ist, was man "spezialisieren" muss, aber in meinem Fall finde ich es perfekt. Vielen Dank! –

0

nicht sicher, es ist die richtige Antwort, aber man konnte eine Basisklasse geschützt Variable, die Sie in den vererbten Klassen während der Initialisierung gesetzt?

zB:

class test 
{ 
    protected string listName; 

    protected void getAllItems() 
    { 
     return getAllItems(listName); 
    } 
} 

class test2 : test 
{ 
    public test2() 
    { 
     base.listName = "MyUniqueList"; 
    } 
} 
+0

Problem dabei ist, dass es das Kind nicht zwingen, den Listennamen einzustellen. Wenn Sie die ursprüngliche Basisklasse nicht geschrieben haben, wie würden Sie es dann einrichten? – ctacke

+0

geschütztes abstraktes Eigentum mit einem erhalten; definiert.Es würde den Entwickler zwingen, es zu implementieren – Sekhat

2

ich wahrscheinlich für den folgenden Ansatz gehen würde:

public abstract class Base 
{ 
    protected List<Items> getAllItems(String listName) 
    { 
     // Implementation 
    } 

    public abstract List<Items> Items 
    { 
     get; 
    } 
} 

public class NewClass : Base 
{ 
    public override List<Items> Items 
    { 
     get 
     { 
      return base.getAllItems("ListNameOfNewClass"); 
     } 
    } 
} 

Dies hält die interne geschützte Funktionalität (getAllItems) getrennt von der öffentlich exponierten Methode/Eigenschaft und bedeutet auch, dass es Stil l Verfügbar für alle Klassen, die von NewClass erben.

Ich habe Ihre Schnittstelle und exponierte sie als Eigenschaft rein aus Dickköpfigkeit verändert! Und Party für alle Fälle wissen Sie tat es getan werden könnte ...

+0

Ich stimme zu, dass ich eine Eigenschaft selbst verwenden würde. Das Problem, das ich bei dieser Implementierung habe, ist jedoch, dass es für einen Entwickler, der später im Projekt mitkommt, verwirrend ist. Sie müssen wissen, dass ihre Items-Eigenschaft zur Basis zurückrufen muss, und das ist überhaupt nicht offensichtlich. – ctacke

+0

Solange die Rolle der Basisklasse gut definiert und dokumentiert ist, glaube ich nicht, dass dies massive Probleme verursachen würde. Aber da ich die Chance hatte, die anderen Antworten zu überdenken, würde ich wahrscheinlich aus diesem Grund zur Komposition gehen. – Justin

0

ich denke, es würde mehr Sinn machen eine dritte Komponente der Umsetzung:

public abstract class BaseClass { 

     protected abstract IList<Item> getAllItems(); 
    } 

    public class SubClass : BaseClass 
    { 
     IItemsProvider itemsProvider; 

     protected override IList<Item> getAllItems() 
     { 
      return itemsProvider.getAllItems("filter"); 
     } 
    } 

    public interface IItemsProvider 
    { 
     IList<Item> getAllItems(string name); 
    } 
+0

Ich weiß nicht, ob ich recht habe, aber ich finde diese Lösung ein wenig zu kompliziert, nein? –

4

Prefer Composition Over Inheritance.

public class Base { 
    private ItemListGetter itemListGetter; // assignment/initialization is up to you 

    private List<Items> getAllItems() { // this can now be inlined 
    return itemListGetter.getList(); 
    } 

} 

Wenn dies der ist einzige Dimension der Variation zwischen Ihren Unterklassen, hier ist keine Vererbung mehr nötig; Legen Sie einfach den richtigen ItemListGetter nach Bedarf fest.

+0

Ich behalte das im Hinterkopf! Danke für deinen Beitrag! :) –

0

Wenn Sie wirklich das Erbe tun wollen, dann würde ich für ctacke's Lösung entscheiden.

Im Allgemeinen scheint jedoch Ihr Problem nicht mit Vererbung gelöst werden. Vererbung sollte nur verwendet werden, um spezialisiertes Verhalten bereitzustellen. In Ihrem Fall scheint es jedoch eher ein Konfigurationsproblem zu sein. Das bedeutet, dass Sie eine Eigenschaft (d. H. Den Listennamen) angeben müssen, die Sie von außen konfigurieren, ohne dass Unterklassen erforderlich sind.

+0

Nun, ich habe auch spezialisierte Methoden, nur nicht in meinem Beispiel. –