class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String me = "son";
}
public void doIt()
{
new Son().printMe();
}
Die Funktion doIt gibt "dad" aus. Gibt es eine Möglichkeit, "Sohn" zu drucken?
java
inheritance
overriding
Dikla
quelle
quelle
Antworten:
Ja. Wenn es sich jedoch um die Variable handelt, wird sie überschrieben (Variablen einen neuen Wert zu geben. Eine neue Definition für die Funktion ist Überschreiben).
Just don't declare the variable but initialize (change) in the constructor or static block.
Der Wert wird bei Verwendung in den Blöcken der übergeordneten Klasse wiedergegeben
Wenn die Variable statisch ist, ändern Sie den Wert während der Initialisierung selbst mit dem statischen Block.
oder sonst im Konstruktor ändern.
Sie können den Wert auch später in beliebigen Blöcken ändern. Es wird sich in der Superklasse widerspiegeln
quelle
class Son extends Dad { static { me = 'son' } }
Kurz gesagt, nein, es gibt keine Möglichkeit, eine Klassenvariable zu überschreiben.
Sie überschreiben Klassenvariablen in Java nicht, Sie verbergen sie. Überschreiben ist zum Beispiel Methoden. Das Verstecken unterscheidet sich vom Überschreiben.
In dem Beispiel, das Sie gegeben haben, verbergen Sie durch Deklarieren der Klassenvariablen mit dem Namen 'me' in class Son die Klassenvariable, die sie von ihrem übergeordneten Dad mit dem gleichen Namen 'me' geerbt hätte. Das Ausblenden einer Variablen auf diese Weise wirkt sich nicht auf den Wert der Klassenvariablen 'me' im Dad der Oberklasse aus.
Für den zweiten Teil Ihrer Frage, wie "Sohn" gedruckt werden soll, würde ich den Wert über den Konstruktor festlegen. Obwohl der folgende Code ziemlich stark von Ihrer ursprünglichen Frage abweicht, würde ich ihn in etwa so schreiben.
Das JLS bietet in Abschnitt 8.3 - Felddeklarationen viel mehr Details zum Verstecken
quelle
Person
soll in diesem Beispiel ersetzt werden?Son
undDad
sollen von erbenPerson
, dannsuper("Son or Dad");
ihre Konstruktoren aufrufen .Ja, überschreiben Sie einfach die
printMe()
Methode:quelle
printMe()
Methode hat oder sogar diese Methode eine statische Methode ist?Sie können einen Getter erstellen und diesen dann überschreiben. Dies ist besonders nützlich, wenn die Variable, die Sie überschreiben, eine Unterklasse von sich selbst ist. Stellen Sie sich vor, Ihre Superklasse hat ein
Object
Mitglied, aber in Ihrer Unterklasse ist dies jetzt definierter alsInteger
.quelle
Wenn Sie es überschreiben wollen, sehe ich keinen gültigen Grund, diese statisch zu halten. Ich würde die Verwendung von Abstraktion vorschlagen (siehe Beispielcode). ::
Jetzt können wir den Vater hinzufügen:
der Sohn:
und Papa traf eine nette Dame:
Sieht so aus, als hätten wir eine Familie. Sagen wir der Welt ihre Namen:
}}
System.out-Ausgabe: Tommy Nancy Dad
System.err ist das gleiche wie oben (hat nur rote Schrift).
JOption-Ausgabe:
Tommy, dann
Nancy, dann
Dad
quelle
Dies sieht aus wie ein Designfehler.
Entfernen Sie das statische Schlüsselwort und legen Sie die Variable beispielsweise im Konstruktor fest. Auf diese Weise setzt Son die Variable in seinem Konstruktor nur auf einen anderen Wert.
quelle
Obwohl es stimmt, dass Klassenvariablen möglicherweise nur in Unterklassen versteckt und nicht überschrieben werden, ist es dennoch möglich, das zu tun, was Sie wollen, ohne
printMe ()
in Unterklassen zu überschreiben , und Reflektion ist Ihr Freund. Im folgenden Code verzichte ich aus Gründen der Übersichtlichkeit auf die Ausnahmebehandlung. Bitte beachten Sie, dass das Deklarierenme
alsprotected
in diesem Zusammenhang wenig sinnvoll erscheint, da es in Unterklassen versteckt wird ...quelle
... druckt "Sohn".
quelle
https://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html
Es heißt Hiding Fields
Über den obigen Link
quelle
nur durch Überschreiben
printMe()
:Der Verweis auf
me
in derDad.printMe
Methode verweist implizit auf das statische FeldDad.me
. Auf die eine oder andere Weise ändern Sie also, wasprintMe
inSon
...quelle
Sie können Variablen in einer Klasse nicht überschreiben. Sie können nur Methoden überschreiben. Sie sollten die Variablen privat halten, da sonst viele Probleme auftreten können.
quelle
Es gibt tatsächlich "Papa" aus, da das Feld nicht überschrieben, sondern ausgeblendet wird. Es gibt drei Ansätze, um "Sohn" zu drucken:
Ansatz 1: printMe überschreiben
Ansatz 2: Verstecken Sie das Feld nicht und initialisieren Sie es im Konstruktor
Ansatz 3: Verwenden Sie den statischen Wert, um ein Feld im Konstruktor zu initialisieren
quelle
Variablen nehmen nicht am Überbinden teil. Nur Methoden tun dies. Ein Methodenaufruf wird zur Laufzeit aufgelöst, dh die Entscheidung zum Aufrufen einer Methode wird zur Laufzeit getroffen, die Variablen werden jedoch nur zur Kompilierungszeit entschieden. Daher wird diese Variable aufgerufen, deren Referenz zum Aufrufen verwendet wird und nicht des Laufzeitobjekts.
Schauen Sie sich folgenden Ausschnitt an:
Wenn Sie den Code ausführen, zeigt die Konsole Folgendes an:
quelle
Natürlich wird empfohlen, private Attribute sowie Getter und Setter zu verwenden, aber ich habe Folgendes getestet, und es funktioniert ... Siehe den Kommentar im Code
Sooo ... habe ich gerade die Vererbungsregeln neu definiert oder Oracle in eine schwierige Situation gebracht? Für mich ist der geschützte statische String me eindeutig überschrieben, wie Sie sehen können, wenn Sie dieses Programm ausführen. Außerdem macht es für mich keinen Sinn, warum Attribute nicht überschreibbar sein sollten.
quelle
Warum sollten Sie Variablen überschreiben, wenn Sie sie in den Unterklassen leicht neu zuweisen können?
Ich folge diesem Muster, um das Sprachdesign zu umgehen. Angenommen, Sie haben eine gewichtige Serviceklasse in Ihrem Framework, die in mehreren abgeleiteten Anwendungen in verschiedenen Varianten verwendet werden muss. In diesem Fall können Sie die Superklassenlogik am besten konfigurieren, indem Sie ihre definierenden Variablen neu zuweisen.
quelle
Nein. Klassenvariablen (gelten auch für Instanzvariablen) weisen in Java keine übergeordnete Funktion auf, da Klassenvariablen auf der Grundlage des Typs des aufrufenden Objekts aufgerufen werden. Es wurde eine weitere Klasse (Mensch) in der Hierarchie hinzugefügt, um dies klarer zu machen. Also jetzt haben wir
Sohn erweitert Vater erweitert Mensch
Im folgenden Code versuchen wir, über ein Array von Human-, Dad- und Son-Objekten zu iterieren, aber es gibt in allen Fällen die Werte der Human Class aus, da der Typ des aufrufenden Objekts Human war.
Wird gedruckt
Wenn wir von einer Referenzvariablen der übergeordneten Klasse auf die Klassenvariable des tatsächlichen Objekts zugreifen möchten, müssen wir dies dem Compiler explizit mitteilen, indem wir die übergeordnete Referenz (menschliches Objekt) in ihren Typ umwandeln.
Wird gedruckt
Wie Teil dieser Frage: - Wie bereits vorgeschlagen, überschreiben Sie die printMe () -Methode in der Son-Klasse und rufen Sie sie dann auf
Die Klassenvariable "me" von Dad wird ausgeblendet, da die nächste Deklaration (von der son class printme () -Methode) des "me" (in der Son-Klasse) Vorrang hat.
quelle
Rufen Sie einfach super.variable im Unterklassenkonstruktor auf
Die Ausgabe ist 10.
quelle