Ich verstehe, dass die Vererbung statischer Methoden in C # nicht unterstützt wird. Ich habe auch eine Reihe von Diskussionen gelesen (einschließlich hier), in denen Entwickler behaupten, dass diese Funktionalität benötigt wird. Die typische Antwort lautet: "Wenn Sie eine statische Mitgliedervererbung benötigen, liegt ein Fehler in Ihrem Design vor."
OK, da OOP nicht möchte, dass ich überhaupt über statische Vererbung nachdenke, muss ich zu dem Schluss kommen, dass mein offensichtlicher Bedarf darauf auf einen Fehler in meinem Design hinweist. Aber ich stecke fest. Ich würde mich sehr über Hilfe bei der Lösung dieses Problems freuen. Hier ist die Herausforderung ...
Ich möchte eine abstrakte Basisklasse erstellen (nennen wir es eine Frucht), die einen komplexen Initialisierungscode enthält. Dieser Code kann nicht in den Konstruktor eingefügt werden, da ein Teil davon auf virtuellen Methodenaufrufen beruht.
Obst wird von anderen konkreten Klassen (Apple, Orange) geerbt, von denen jede eine Standard-Factory-Methode CreateInstance () verfügbar machen muss, um eine Instanz zu erstellen und zu initialisieren.
Wenn eine Vererbung statischer Elemente möglich wäre, würde ich die Factory-Methode in die Basisklasse einfügen und einen virtuellen Methodenaufruf an die abgeleitete Klasse verwenden, um den Typ zu erhalten, von dem eine konkrete Instanz initialisiert werden muss. Der Client-Code würde einfach Apple.CreateInstance () aufrufen, um eine vollständig initialisierte Apple-Instanz zu erhalten.
Dies ist jedoch eindeutig nicht möglich. Kann jemand erklären, wie sich mein Design ändern muss, um die gleiche Funktionalität zu gewährleisten?
quelle
Antworten:
Eine Idee:
Und ruf so an:
Keine zusätzlichen Fabrikklassen erforderlich.
quelle
Apple
Konstruktor nicht weniger als öffentlich machen, da dies einen öffentlichen Konstruktorwhere T : Fruit<T>, new()
vorschreibtT
. @ Matt Hamsmith - Ihr Code wird erst kompiliert, wenn Sie ihn entfernenprotected Apple() { }
. Ich habe es bereits in VS getestet.Verschieben Sie die Factory-Methode aus dem Typ und fügen Sie sie in eine eigene Factory-Klasse ein.
Wenn ich mir das anschaue, ist es nicht erforderlich, die Create-Methode in eine eigene Factory-Klasse zu verschieben (obwohl ich denke, dass dies vorzuziehen ist - Trennung von Bedenken -). Sie können sie in die Fruit-Klasse einfügen:
Und um zu sehen, ob es funktioniert:
quelle
Warum nicht eine Factory-Klasse (mit Vorlagen) mit einer create-Methode erstellen?
quelle
Ich würde so etwas tun
quelle
Die
WebRequest
Klasse und ihre Ableitungstypen in der .NET BCL sind ein gutes Beispiel dafür, wie diese Art von Design relativ gut implementiert werden kann.Die
WebRequest
Klasse hat mehrere Unterklassen, einschließlichHttpWebRequest
undFtpWebReuest
. DieseWebRequest
Basisklasse ist jetzt auch ein Factory-Typ und macht eine statischeCreate
Methode verfügbar (die Instanzkonstruktoren sind ausgeblendet, wie es das Factory-Muster erfordert).Diese
Create
Methode gibt eine bestimmte Implementierung von zurückWebRequest
Klasse zurück und bestimmt anhand des URI (oder der URI-Zeichenfolge) den Objekttyp, der erstellt und zurückgegeben werden soll.Dies hat das Endergebnis des folgenden Verwendungsmusters:
Ich persönlich denke, dies ist ein guter Weg, um das Problem anzugehen, und es scheint tatsächlich die bevorzugte Methode der .NET Framework-Ersteller zu sein.
quelle
Erstens bedeutet das Fehlen von statischen Initialisierern, die virtuell sein können, nicht, dass Sie keine "Standard" -Mitgliedmethoden haben können, die überladen sein könnten. Zweitens können Sie Ihre virtuellen Methoden von Konstruktoren aus aufrufen, und sie funktionieren wie erwartet, sodass hier kein Problem auftritt. Drittens können Sie Generika verwenden, um eine typsichere Fabrik zu haben.
Hier ist ein Code, der die vom Konstruktor aufgerufene Methode factory + member Initialize () verwendet (und geschützt ist, sodass Sie sich keine Sorgen machen müssen, dass jemand sie nach dem Erstellen eines Objekts erneut aufruft):
quelle
Ich würde sagen, das Beste ist, eine virtuelle / abstrakte Initialisierungsmethode für die Fruchtklasse zu erstellen, die aufgerufen werden muss, und dann eine externe 'Fruchtfabrik'-Klasse zu erstellen, um Instanzen zu erstellen:
quelle