Direkt über den parent-Konstruktor aufrufen, Großeltern
Das problem ist Folgendes: ich habe eine abstrakte Klasse, die einige arbeiten in seinem Konstruktor, und eine Reihe von untergeordneten Klassen, implementieren Sie die abstrakte Klasse:
class AbstractClass {
AbstractClass(){ /* useful implementation */ }
}
class ConcreteClass1 extends AbstractClass {
ConcreteClass1(){ super(); /* useful implementation */ }
}
Dann die konkreten Klassen müssen angepasst werden und eine Lösung ist zu verlängern die konkreten Klassen:
class CustomizedClass1 extends ConcreteClass1 {
CustomizedCLass1(){ super(); /* useful implementation */ }
}
ABER das problem ist, dass die angepassten Klassen müssen nur zu nennen die abstrakte Klasse Konstruktor und nicht die konkrete Klasse Konstruktor.
Wie erreichen Sie diese? Vorschläge, die Klasse zu wechseln die Beziehungen gültig sind.
EDIT: Das konkrete Beispiel ist, dass ConcreteClass1 und CustomizedClass1 haben unterschiedliche Sätze von Daten (ConcreteData1 und CustomizedData1), und es ist aus der Datenbank abgerufen im Konstruktor der Klasse. Das problem ist, dass das erstellen einer Instanz von CustomizedClass1 abrufen von Daten-Entitäten.
Ich bin mir bewusst, dass mit einfachen Vererbung es ist wahrscheinlich nicht die beste Sache zu tun, deshalb habe ich darauf hingewiesen, dass Vorschläge, die Klasse zu wechseln die Beziehungen gültig sind.
ConcreteClass1
Konstruktor, es ist nicht ein ConcreteClass1
.Einige Antworten zeigen einige tricks, um dies zu tun, aber dies SEHR unnatürlich in Java und OO. Die besten Antworten werden eine große Herausforderung für Ihr Objekt-design und Sie ermutigen, zu denken ist-Ein und hat-Ein Beziehungen.
Aber die Geschwindigkeit der Entwicklung kann manchmal auch egal, nicht wahr?
Verwandte Themen: stackoverflow.com/questions/586363/...
InformationsquelleAutor German | 2009-12-10
Du musst angemeldet sein, um einen Kommentar abzugeben.
Einfach (aber warum?):
Meine karitativen Vermutung ist in ConcreteClass1 er tun könnte, einige der Initialisierung von externen Ressourcen, und in CustomizedClass1 er will verschiedene externe Ressourcen initialisiert.
wenn dies der Fall ist, dann braucht er wohl eine Klasse erstellen, ist ein Geschwister von den Eltern erhalten, oder umgestalten ConcreteClass1 in zwei verschiedenen Klassen.
Einfach, weil es unterschiedliche Initialisierung würden Sie empfehlen die Schaffung einer anderen Klasse, die hat keinerlei Verhalten? Ich kann mir denken, viele Fälle, wo dies das gewünschte Verhalten.
InformationsquelleAutor MattMcKnight
Du das nicht in Java. Ich oft Studenten, die das machen wollen, aber ich habe nie gesehen ein Fall, wo es wirklich das ist, was Sie tun wollte.
Können Sie ein konkretes Beispiel nennen, was es ist, Sie tun möchten und warum (deine Beschreibung ist zu vage), und ich bin sicher, dass eine Lösung erreicht werden kann 🙂
Edit:
Für ein Beispiel aus der Praxis, warum Sie nicht wollen, dies zu tun (normalerweise) wäre eine Hierarchie wie:
Wenn der Mensch Konstruktor könnte überspringen die Mammal-Konstruktor dann würden Sie wind mit ein Mensch, hat keine Lungen... nicht sehr nützlich.
Dann der Konstruktor von Mammal "Atmung-Mechanismus" als argument für den Konstruktor und weisen, dass die Instanz-Variablen, die verwendet werden, um die Lunge 🙂
Ich denke, der Punkt dieses fehlt, ist, dass die Mammal-Konstruktor ist nicht unbedingt idempotent, und Sie wollen nicht immer zum aufrufen der gleichen Konstruktor von einer Unterklasse. Sie immer noch müssen sich auf mindestens einen Konstruktor, aber nicht jeder braucht die gleichen Konstruktor.
Ich würde sagen, wenn Sie haben Konstruktoren initialisieren der Klasse in völlig unterschiedliche Wege, dann sind Sie wahrscheinlich, etwas "falsch".
Wenn Aquaman hat Kiemen statt Lunge, dann ist er ein Amphibien -, kein Säugetier. Trotzdem - die Charakteristik, die eindeutig ein Säugetier ist der Milchdrüsen - Reptilien haben Lungen zu!
InformationsquelleAutor TofuBeer
Jede Instanz von
CustomizedClass1
ist auch eine Instanz vonConcreteClass1
, per definition, so dass es muss konstruiert werden als eine gültigeConcreteClass1
Instanz vor derCustomizedClass1
Konstruktor ausgeführt werden kann. Ansonsten, was passieren würde, wenn Sie aufgerufenConcreteClass1
Methoden auf? Sie würden versuchen, den Betrieb auf Variablen, die nicht initialisiert wurden noch.Wenn Sie denken, Sie brauchen, um dies zu tun, die Chancen sind Ihre design-Anforderungen neu zu denken. Wenn Sie nur einige Funktionen von
ConcreteClass1
zum Beispiel, dass die Funktionalität könnte sein, factored in ein OberklasseConcreteClass1
, undCustomizedClass1
verlängern könnte, dass man nur die Funktionalität, die er benötigt.Bitte geben Sie mehr Informationen über die Beziehung zwischen diesen Klassen.
InformationsquelleAutor Wyzard
Zwei Kommentare:
Erstens, Sie sind eigentlich nicht zu denken, im Sinne von "springen über' Konstruktoren wie diese.
Zweitens, es wirklich klingt wie Sie brauchen, um zu überdenken Sie Ihre Klasse Beziehungen.
Jeder Zeit finden Sie sich selbst denken "A extends B, außer, dass..." ist eine sehr gute Zeit, um an Sachen weiter. 'Erweitert' impliziert 'ist ein', das ist eine entweder/oder-Beziehung: mit optionalen Verhalten fügt Grauzonen, die beißen, die Sie später auf.
Als die Leute gesagt haben, Sie könnten mehrere Konstruktoren auf ConcreteClass1 zu tun, die Initialisierung benötigen Sie in jedem Fall, vielleicht macht Sie geschützt, so dass Sie nur verwendet werden kann, die von Unterklassen. Aber hier ist eine Frage: was ist, wenn jemand schreiben will CustomizedClass2, die einige (aber nicht alle) Funktionen, die in ConcreteClass1? Fügen Sie einen anderen benutzerdefinierten Konstruktor?
In Ihrem Beispiel kann es sein, eine bessere zu entwerfen (und anzeigen) ConcreteClass1 als eine 'Schweizer-Messer' anpassbare Klasse (das kann sowohl geerbt und instanziiert auf seine eigene) im Vorfeld. Also ja, wenn Sie wirklich vergessen, über die benötigte Funktionalität (oder die Anforderungen haben sich geändert) und auf jeden Fall müssen Sie genau die ConcreteClass1 Klasse als Grundlage für die CustomizedClass2 -- fügen Sie geeignete Methoden (inkl. Konstruktoren) oder die Anpassung der bestehenden. Das könnte eine überlegung hinter dem Thema-starter-design.
InformationsquelleAutor julian_t
Das klingt für mich wie eine Mischung aus Bedenken - etwas, was Java nicht gerüstet sind.
Es ist zwar nicht die Antwort, die Sie erhofft hatten, oder einen, ich bin stolz darauf, zu geben, können Sie einfach erstellen
ConcreteClass2
nachahmtConcreteClass1
und nutzt dieAbstractClass
's Konstruktor.Als @TofuBeer gesagt, dies ist nicht etwas, das Java unterstützt. Dies ist, warum einige moderne Programmiersprachen (z.B. Scala w/Merkmale) sind auf dem Vormarsch, passionierten Entwicklern.
InformationsquelleAutor rynmrtn
Ist CustomizedData1 eine Unterklasse von ConcreteData1? Wenn dem so ist, dann würde ich vorschlagen einen (evtl. protected) Konstruktor für ConcreteClass1, nimmt in einer ConcreteData1 zu verwenden, anstatt das abrufen Ihrer eigenen während der Initialisierung. Auf diese Weise, CustomizedClass1 Holen kann seinen CustomizedData1 und übergeben es an den Aufruf super. Leider kann dies schwierig sein, oder ziemlich unmöglich, wenn man nicht das abrufen der Daten vor einige interne init.
Aber dann CustomizedClass1 muss wahrscheinlich eine Referenz zu den Daten als ein CustomizedData1 nicht nur eine ConcreteData1. Es könnte genau festgelegten übernommenen ConcreteData1 die ganze Zeit, aber das scheint yucky. Aber wenn er speichert seine eigene Referenz, um die Daten, dann ist es notwendig zu halten, werden die Referenzen in sync, wenn Sie nicht endgültig.
InformationsquelleAutor user401321
Warum nicht einfach anpassen und neu erstellt
ConcreteClass1
Instanz zu Verhalten, wie einAbstractClass
Instanz (vorausgesetzt, dassConcreteClass1
den entsprechenden protected-Methoden nur für die)? I. e.:Design-Intentionen und die Logik kann dabei wie folgt:
Sie wollen, um die (Grund -) Verhalten von
ConcreteClass1
über Vererbung, Erben Sie von ihm (natürlich auferlegt, die es entwerfen, lohnt sich Erben von).Möchten Sie das Verhalten anpassen, zur Verfügung gestellt von
ConcreteClass1
standardmäßig. Die Anpassung, die Sie erreichen möchten, können in der Regel beschrieben werden, mit einigen Parametern. Nur übergeben Sie diese Parameter, um eine spezielle Methode derCustomizedClass1
(die geschützt werden), und nennen Sie escustomize()
entsprechend.Die Anpassung erfolgt in der
ConcreteClass1()
Konstruktor kann beliebig sein, insbesondere die Klasse-Instanz-Verhaltens werden können "rückgängig gemacht," dass derAbstractClass
, sind Sie wahrscheinlich Fragen, für (wenn ich es richtig machen).Aufrufen
customize_with()
tatsächlich stellen einige overhead in Abhängigkeit von den tatsächlichen Sachen, die inConcreteClass1()
- in diesem Fall mithilfe überlastet (und möglicherweise Schutz) - Konstruktoren ist definitiv eine bessere Lösung, es sei denn, Sie möchtenConcreteClass1
' - Instanzen werden dynamisch anpassbar (in dem Fallcustomize_with()
- und wahrscheinlich der rest derConcreteClass1
sollten entsprechend ausgelegt sein, d.h. die Unterstützung solcher Verhalten durch Vertrag).Entschuldigen Sie mich, wenn etwas falsch mit der syntax (ich habe nicht geschrieben, viel Java-code).
Xu Möglicherweise aber auch Fragen auf, wie-zu-tun-Hack verdienen etwas besser-praxisorientierte Antworten! In anderen Worten, diese Lösung versucht, etwas zu erreichen, besser (oder zumindest denke ich so 🙂 ). Cheeers!
InformationsquelleAutor
Einer Weise, die ich kam mit:
In dieser Weise, CustomizedClass1 wird das Verhalten muss es von AbstractClass ohne durch ConcreteClass1 Initialisierungen.
EDIT: Autsch, das funktioniert nicht, weil die Eltern Konstruktoren werden implizit aufgerufen, als einer der Kommentatoren darauf hingewiesen, ich denke, der einfache Weg ist, haben verschiedene Konstruktoren.
Könnten Sie bitte den Namen der crazy? :)))
Deins ist nicht verrückt...es ist eigentlich ziemlich nah an diese Antwort. Die verrückten sind diejenigen, die nehmen diesen Kerl, holzlege für nicht bitten, seine Frage klar, so dass Sie nachweisen können, Ihren "starken" Objekt-Orientierten Verständnis.
Es kam nur zu mir,, Deutsche,, dass Sie falsch in seinem Beispiel - ConcreteClass1 Initialisierungen werden nicht übergeben, habe es gerade getestet, um sicher zu sein, die Quelle-Datei bei <languageblah.googlecode.com/files/Main.java>
Das ist, weil die Sprache erzwingt immer den Aufruf der parent-Konstruktor und in Ihrem Fall ist dieser Aufruf ist eine Art implizite und automatisch generierten (weil der parent-Konstruktor hat keine Argumente also ist die Standard-Einstellung).
InformationsquelleAutor German
Ja, Sie können zwicken! Fügen Sie eine andere Methode der übergeordneten Klasse(B) und in Ihrem Kind Klasse(C) nennen es als super.executeParentA(); der Aufruf dieser Methode super.execute()
-Mehboob
InformationsquelleAutor Mehboob
Ich denken kann von zwei Fällen, wo man dies möglicherweise tun möchten (eigentlich nicht):
Fall 1, ConcreteClass2 läuft freigegebenen Initialisierung aus der top-Klasse, aber macht dann seine eigene Initialisierung, die verschiedenen Konflikte, als die, die in ConcreteClass1 -> haben eine init () - Methode außer Kraft setzen (anstatt zu versuchen, zu überschreiben ConcreteClass1 Konstruktor).
Fall 2 Sie haben polymorphe Initialisierung eines (oder mehrere) Klasse (das ist eigentlich ein Sonderfall der vorherigen):
In diesem Fall, entweder die Verwendung der init () - Ansatz, oder tun Sie dies:
In anderen Worten, stellen Sie den Grund für den Sprung explizit, implizit Sprung über die Hierarchie ist verboten und für den guten Gründen (siehe andere Antworten.
InformationsquelleAutor zakmck