Warum ist es nicht möglich, statische Methoden zu überschreiben?
Wenn möglich, verwenden Sie bitte ein Beispiel.
java
static
overriding
static-methods
Sgokhales
quelle
quelle
Parent p = new Child()
undp.childOverriddenStaticMethod()
der Compiler es dann auflöst,Parent.childOverriddenStaticMethod()
indem er sich den Referenztyp ansieht.Antworten:
Das Überschreiben hängt von einer Instanz einer Klasse ab. Der Punkt des Polymorphismus besteht darin, dass Sie eine Klasse unterklassifizieren können und die Objekte, die diese Unterklassen implementieren, unterschiedliche Verhaltensweisen für dieselben Methoden aufweisen, die in der Oberklasse definiert (und in den Unterklassen überschrieben) sind. Eine statische Methode ist keiner Instanz einer Klasse zugeordnet, sodass das Konzept nicht anwendbar ist.
Es gab zwei Überlegungen, die das Design von Java beeinflussten. Eines war ein Problem mit der Leistung: Smalltalk wurde vielfach kritisiert, weil es zu langsam sei (Garbage Collection und polymorphe Aufrufe seien Teil davon), und Javas Entwickler waren entschlossen, dies zu vermeiden. Ein weiterer Grund war die Entscheidung, dass die Zielgruppe für Java C ++ - Entwickler waren. Statische Methoden so funktionieren zu lassen, wie sie es tun, war für C ++ - Programmierer von Vorteil und auch sehr schnell, da nicht bis zur Laufzeit gewartet werden muss, um herauszufinden, welche Methode aufgerufen werden soll.
quelle
objects
) das Überladen von Methoden.obj.staticMethod()
) aufgerufen wird - was zulässig ist und die Typen zur Kompilierungszeit verwendet. Wenn sich der statische Aufruf in einer nicht statischen Methode einer Klasse befindet, kann das "aktuelle" Objekt ein abgeleiteter Typ der Klasse sein. Statische Methoden, die für die abgeleiteten Typen definiert sind, werden jedoch nicht berücksichtigt (sie sind vom Laufzeittyp Hierarchie).Persönlich denke ich, dass dies ein Fehler im Design von Java ist. Ja, ja, ich verstehe, dass nicht statische Methoden an eine Instanz angehängt sind, während statische Methoden an eine Klasse usw. angehängt sind. Beachten Sie dennoch den folgenden Code:
Dieser Code funktioniert nicht wie erwartet. SpecialEmployee's erhalten nämlich einen Bonus von 2%, genau wie reguläre Mitarbeiter. Wenn Sie jedoch die "statischen" entfernen, erhalten SpecialEmployee einen Bonus von 3%.
(Zugegeben, dieses Beispiel ist insofern ein schlechter Codierungsstil, als Sie im wirklichen Leben wahrscheinlich möchten, dass sich der Bonusmultiplikator irgendwo in einer Datenbank befindet und nicht fest codiert. Aber das liegt nur daran, dass ich das Beispiel nicht mit vielem festhalten wollte von Code für den Punkt irrelevant.)
Es scheint mir ziemlich plausibel, dass Sie getBonusMultiplier statisch machen möchten. Vielleicht möchten Sie in der Lage sein, den Bonusmultiplikator für alle Kategorien von Mitarbeitern anzuzeigen, ohne dass in jeder Kategorie eine Instanz eines Mitarbeiters erforderlich ist. Was wäre der Sinn der Suche nach solchen Beispielinstanzen? Was ist, wenn wir eine neue Kategorie von Mitarbeitern erstellen und noch keine Mitarbeiter zugewiesen haben? Dies ist logischerweise eine statische Funktion.
Aber es funktioniert nicht.
Und ja, ja, ich kann mir eine beliebige Anzahl von Möglichkeiten vorstellen, den obigen Code neu zu schreiben, damit er funktioniert. Mein Punkt ist nicht, dass es ein unlösbares Problem schafft, sondern dass es eine Falle für den unachtsamen Programmierer schafft, weil sich die Sprache nicht so verhält, wie ich es von einer vernünftigen Person erwarten würde.
Wenn ich versuchen würde, einen Compiler für eine OOP-Sprache zu schreiben, würde ich schnell erkennen, warum es schwierig oder unmöglich wäre, ihn so zu implementieren, dass statische Funktionen überschrieben werden können.
Oder vielleicht gibt es einen guten Grund, warum sich Java so verhält. Kann jemand auf einen Vorteil dieses Verhaltens hinweisen, eine Kategorie von Problemen, die dadurch erleichtert wird? Ich meine, zeige mich nicht nur auf die Java-Sprachspezifikation und sage "siehe, das ist dokumentiert, wie es sich verhält". Ich weiß das. Aber gibt es einen guten Grund, warum es sich so verhalten sollte? (Abgesehen von dem offensichtlichen "es richtig zu machen war zu schwer" ...)
Aktualisieren
@VicKirk: Wenn Sie meinen, dass dies "schlechtes Design" ist, weil es nicht dazu passt, wie Java mit Statik umgeht, lautet meine Antwort: "Nun, duh, natürlich." Wie ich in meinem ursprünglichen Beitrag sagte, funktioniert es nicht. Aber wenn Sie meinen, dass es schlechtes Design in dem Sinne ist, dass mit einer Sprache, in der dies funktioniert, etwas grundlegend falsch wäre, dh wenn die Statik genau wie virtuelle Funktionen überschrieben werden könnte, würde dies irgendwie zu einer Mehrdeutigkeit führen oder es wäre unmöglich Effizient implementieren oder so, antworte ich: "Warum? Was ist los mit dem Konzept?"
Ich denke, das Beispiel, das ich gebe, ist eine sehr natürliche Sache, die ich tun möchte. Ich habe eine Klasse mit einer Funktion, die nicht von Instanzdaten abhängt und die ich möglicherweise sehr vernünftigerweise unabhängig von einer Instanz sowie innerhalb einer Instanzmethode aufrufen möchte. Warum sollte das nicht funktionieren? Ich bin im Laufe der Jahre ziemlich oft in diese Situation geraten. In der Praxis kann ich das umgehen, indem ich die Funktion virtuell mache und dann eine statische Methode erstelle, deren einziger Lebenszweck darin besteht, eine statische Methode zu sein, die den Aufruf mit einer Dummy-Instanz an die virtuelle Methode weiterleitet. Das scheint ein sehr umständlicher Weg dorthin zu sein.
quelle
someStatic()
und B A erweitert, dannB.someMethod()
an die Methode in A bindet . Wenn ich anschließendsomeStatic()
zu B hinzufüge , wird der aufrufende Code immer noch aufgerufen,A.someStatic()
bis ich den aufrufenden Code neu kompiliere. Es hat mich auch überrascht, dassbInstance.someStatic()
der deklarierte Typ von bInstance verwendet wird, nicht der Laufzeittyp, da er beim Kompilieren nicht verknüpft wird.A bInstance; ... bInstance.someStatic()
Daher wird A.someStatic () aufgerufen, wenn B.someStatic () vorhanden ist.Die kurze Antwort lautet: Es ist durchaus möglich, aber Java tut es nicht.
Hier ist ein Code, der den aktuellen Stand der Dinge in Java veranschaulicht :
Datei
Base.java
:Datei
Child.java
:Wenn Sie dies ausführen (ich habe es auf einem Mac von Eclipse mit Java 1.6 ausgeführt), erhalten Sie:
Hier scheinen die einzigen Fälle, die eine Überraschung sein könnten (und um die es in der Frage geht), der erste Fall zu sein:
"Der Laufzeittyp wird nicht verwendet, um zu bestimmen, welche statischen Methoden aufgerufen werden, selbst wenn sie mit einer Objektinstanz (
obj.staticMethod()
) aufgerufen werden ."und der letzte Fall:
"Wenn Sie eine statische Methode aus einer Objektmethode einer Klasse aufrufen, wird die statische Methode ausgewählt, auf die von der Klasse selbst zugegriffen werden kann, und nicht von der Klasse, die den Laufzeittyp des Objekts definiert."
Aufruf mit einer Objektinstanz
Der statische Aufruf wird zur Kompilierungszeit aufgelöst, während ein nicht statischer Methodenaufruf zur Laufzeit aufgelöst wird. Beachten Sie, dass statische Methoden zwar vom Elternteil geerbt werden, aber nicht vom Kind überschrieben werden. Dies könnte eine Überraschung sein, wenn Sie etwas anderes erwartet haben.
Aufruf aus einer Objektmethode heraus
Objektmethodenaufrufe werden unter Verwendung des Laufzeittyps aufgelöst, statische ( Klassen- ) Methodenaufrufe werden jedoch unter Verwendung des Typs zur Kompilierungszeit (deklariert) aufgelöst.
Regeln ändern
Um diese Regeln so zu ändern, dass beim letzten Aufruf im aufgerufenen Beispiel
Child.printValue()
statische Aufrufe zur Laufzeit mit einem Typ versehen werden müssen, anstatt dass der Compiler den Aufruf zur Kompilierungszeit mit der deklarierten Klasse des Objekts (oder) auflöst Kontext). Statische Aufrufe könnten dann die (dynamische) Typhierarchie verwenden, um den Aufruf aufzulösen, so wie es Objektmethodenaufrufe heute tun.Dies wäre leicht machbar (wenn wir Java: -O ändern würden) und ist keineswegs unvernünftig, hat jedoch einige interessante Überlegungen.
Die Hauptüberlegung ist, dass wir entscheiden müssen, welche statischen Methodenaufrufe dies tun sollen.
Im Moment hat Java diese "Eigenart" in der Sprache, in der
obj.staticMethod()
Anrufe durchObjectClass.staticMethod()
Anrufe ersetzt werden (normalerweise mit einer Warnung). [ Hinweis:ObjectClass
ist der Typ zur Kompilierungszeit vonobj
.] Dies wären gute Kandidaten, um auf diese Weise den Laufzeittyp von zu überschreibenobj
.Wenn wir dies tun würden, wäre das Lesen von Methodenkörpern schwieriger: Statische Aufrufe in einer übergeordneten Klasse könnten möglicherweise dynamisch "umgeleitet" werden. Um dies zu vermeiden, müssten wir die statische Methode mit einem Klassennamen aufrufen - und dies macht die Aufrufe mit der Hierarchie des Typs zur Kompilierungszeit (wie jetzt) offensichtlicher aufgelöst.
Die anderen Möglichkeiten zum Aufrufen einer statischen Methode sind schwieriger: Sie
this.staticMethod()
sollten dasselbe bedeuten wieobj.staticMethod()
die Verwendung des Laufzeit-Typs vonthis
. Dies kann jedoch zu Kopfschmerzen bei vorhandenen Programmen führen, die (anscheinend lokale) statische Methoden ohne Dekoration aufrufen (was wohl gleichbedeutend ist mitthis.method()
).Was ist also mit schmucklosen Anrufen
staticMethod()
? Ich schlage vor, dass sie dasselbe tun wie heute und den lokalen Klassenkontext verwenden, um zu entscheiden, was zu tun ist. Andernfalls würde große Verwirrung entstehen. Natürlich bedeutet dies , dassmethod()
würde bedeuten ,this.method()
wennmethod
eine nicht-statische Methode war, undThisClass.method()
wennmethod
eine statische Methode war. Dies ist eine weitere Quelle der Verwirrung.Andere Überlegungen
Wenn wir dieses Verhalten geändert (und machte einen statischen Aufruf potenziell dynamisch nicht-lokal), würden wir wahrscheinlich wollen die Bedeutung zu überdenken
final
,private
undprotected
als Qualifier aufstatic
Methoden einer Klasse. Wir müssten uns dann alle daran gewöhnen, dassprivate static
undpublic final
Methoden nicht überschrieben werden und daher zur Kompilierungszeit sicher aufgelöst werden können und als lokale Referenzen "sicher" zu lesen sind.quelle
Eigentlich haben wir uns geirrt.
Obwohl Java das standardmäßige Überschreiben statischer Methoden nicht zulässt, können Sie bei gründlicher Durchsicht der Dokumentation von Klassen- und Methodenklassen in Java dennoch eine Möglichkeit finden, statische Methoden zu überschreiben, indem Sie die folgende Problemumgehung umgehen:
Resultierende Ausgabe:
was wir erreichen wollten :)
Selbst wenn wir die dritte Variable Carl als RegularEmployee deklarieren und ihr die Instanz von SpecialEmployee zuweisen, haben wir im ersten Fall den Aufruf der RegularEmployee-Methode und im zweiten Fall den Aufruf der SpecialEmployee-Methode
Schauen Sie sich einfach die Ausgabekonsole an:
;)
quelle
Statische Methoden werden von der JVM als global behandelt, sie sind überhaupt nicht an eine Objektinstanz gebunden.
Es könnte konzeptionell möglich sein, statische Methoden von Klassenobjekten aufzurufen (wie in Sprachen wie Smalltalk), aber dies ist in Java nicht der Fall.
BEARBEITEN
Sie können statische Methoden überladen , das ist in Ordnung. Sie können eine statische Methode jedoch nicht überschreiben , da Klassen kein erstklassiges Objekt sind. Sie können Reflection verwenden, um die Klasse eines Objekts zur Laufzeit abzurufen, aber das Objekt, das Sie erhalten, entspricht nicht der Klassenhierarchie.
Sie können über die Klassen nachdenken, aber es hört dort auf. Sie rufen keine statische Methode mit
clazz1.staticMethod()
, sondern mit aufMyClass.staticMethod()
. Eine statische Methode ist nicht an ein Objekt gebunden und daher gibt es weder eine Vorstellungthis
nochsuper
eine statische Methode. Eine statische Methode ist eine globale Funktion. Infolgedessen gibt es auch keine Vorstellung von Polymorphismus, und daher macht das Überschreiben von Methoden keinen Sinn.Dies könnte jedoch möglich sein, wenn
MyClass
es sich zur Laufzeit um ein Objekt handelt, für das Sie eine Methode aufrufen, wie in Smalltalk (oder vielleicht JRuby, wie ein Kommentar andeutet, aber ich weiß nichts über JRuby).Oh ja ... noch eine Sache. Sie können eine statische Methode über ein Objekt aufrufen,
obj1.staticMethod()
aber dieser wirklich syntaktische Zucker fürMyClass.staticMethod()
und sollte vermieden werden. In der modernen IDE wird normalerweise eine Warnung ausgegeben. Ich weiß nicht, warum sie diese Abkürzung jemals zugelassen haben.quelle
clazz2 instanceof clazz1
richtig zu verwenden, können Sie stattdessen verwendenclass2.isAssignableFrom(clazz1)
, was meiner Meinung nach in Ihrem Beispiel wahr zurückgeben würde.Das Überschreiben von Methoden wird durch dynamisches Dispatching ermöglicht. Dies bedeutet, dass der deklarierte Typ eines Objekts nicht sein Verhalten bestimmt, sondern seinen Laufzeit-Typ:
Obwohl beide
lassie
undkermit
als Objekte vom Typ deklariert sind, variiertAnimal
ihr Verhalten (Methode.speak()
), da das dynamische Dispatching den Methodenaufruf nur zur Laufzeit an eine Implementierung bindet.speak()
- nicht zur Kompilierungszeit.Hier
static
beginnt das Schlüsselwort Sinn zu machen: Das Wort "statisch" ist ein Antonyme für "dynamisch". Der Grund, warum Sie statische Methoden nicht überschreiben können, liegt darin, dass statische Elemente nicht dynamisch verteilt werden - weil statisch wörtlich "nicht dynamisch" bedeutet. Wenn sie dynamisch versendet würden (und somit überschrieben werden könnten), würde dasstatic
Schlüsselwort einfach keinen Sinn mehr ergeben.quelle
Ja. In der Praxis erlaubt Java das Überschreiben statischer Methoden. Wenn Sie eine statische Methode in Java überschreiben, wird sie theoretisch kompiliert und reibungslos ausgeführt, verliert jedoch den Polymorphismus, der die grundlegende Eigenschaft von Java ist. Sie werden überall lesen, dass es nicht möglich ist, sich selbst zu kompilieren und auszuführen. Sie werden Ihre Antwort bekommen. Beispiel: Wenn Sie Class Animal und eine statische Methode eat () haben und diese statische Methode in ihrer Unterklasse überschreiben, nennen wir sie Dog. Wenn dann, wo immer Sie ein Hundeobjekt einer Tierreferenz zuweisen und eat () gemäß Java Dog aufrufen, sollte eat () aufgerufen worden sein, aber in statischen Overriding Animals wird eat () aufgerufen.
Nach dem Polymorphismus-Prinzip von Java sollte die Ausgabe sein
Dog Eating
.Das Ergebnis war jedoch anders, da Java zur Unterstützung des Polymorphismus die späte Bindung verwendet. Dies bedeutet, dass Methoden nur zur Laufzeit aufgerufen werden, bei statischen Methoden jedoch nicht. Bei statischen Methoden ruft der Compiler Methoden zur Kompilierungszeit und nicht zur Laufzeit auf, sodass wir Methoden gemäß der Referenz und nicht gemäß dem Objekt erhalten, die eine Referenz enthalten. Deshalb kann man sagen, dass er statisches Überringen praktisch unterstützt, theoretisch jedoch nicht 't.
quelle
Das Überschreiben ist beispielsweise Mitgliedern vorbehalten, um das polymorphe Verhalten zu unterstützen. statische Klassenmitglieder gehören nicht zu einer bestimmten Instanz. Stattdessen gehören statische Mitglieder zur Klasse und daher wird das Überschreiben nicht unterstützt, da Unterklassen nur geschützte und öffentliche Instanzmitglieder und keine statischen Mitglieder erben. Möglicherweise möchten Sie eine Inerface- und Research Factory- und / oder Strategiedesignmuster definieren, um einen alternativen Ansatz zu bewerten.
quelle
In Java (und vielen OOP-Sprachen, aber ich kann nicht für alle sprechen; und einige haben überhaupt keine statische Sprache) haben alle Methoden eine feste Signatur - die Parameter und Typen. In einer virtuellen Methode ist der erste Parameter impliziert: ein Verweis auf das Objekt selbst und beim Aufruf aus dem Objekt heraus fügt der Compiler automatisch hinzu
this
.Bei statischen Methoden gibt es keinen Unterschied - sie haben immer noch eine feste Signatur. Indem Sie die Methode als statisch deklarieren, haben Sie ausdrücklich angegeben, dass der Compiler den implizierten Objektparameter am Anfang dieser Signatur nicht einschließen darf. Daher darf kein anderer Code, der dies aufruft, versuchen, einen Verweis auf ein Objekt auf dem Stapel zu platzieren . Wenn dies der Fall wäre, würde die Methodenausführung nicht funktionieren, da sich die Parameter an der falschen Stelle - um eins verschoben - auf dem Stapel befinden würden.
Wegen dieses Unterschieds zwischen den beiden; Virtuelle Methoden haben immer einen Verweis auf das Kontextobjekt (dh
this
), sodass es möglich ist, auf alles innerhalb des Heaps zu verweisen, das zu dieser Instanz des Objekts gehört. Bei statischen Methoden kann diese Methode jedoch nicht auf Objektvariablen und -methoden zugreifen, da keine Referenz übergeben wird, da der Kontext nicht bekannt ist.Wenn Sie möchten, dass Java die Definition so ändert, dass für jede statische oder virtuelle Methode ein Objektkontext übergeben wird, haben Sie im Wesentlichen nur virtuelle Methoden.
Wie jemand in einem Kommentar zur Operation gefragt hat - was ist Ihr Grund und Zweck, diese Funktion zu wollen?
Ich kenne Ruby nicht sehr gut, da dies vom OP erwähnt wurde, habe ich einige Nachforschungen angestellt. Ich sehe, dass in Ruby Klassen wirklich eine besondere Art von Objekt sind und man (sogar dynamisch) neue Methoden erstellen kann. Klassen sind vollständige Klassenobjekte in Ruby, sie sind nicht in Java. Dies ist nur etwas, was Sie akzeptieren müssen, wenn Sie mit Java (oder C #) arbeiten. Dies sind keine dynamischen Sprachen, obwohl C # einige Formen der Dynamik hinzufügt. In Wirklichkeit hat Ruby keine "statischen" Methoden, soweit ich sie finden konnte - in diesem Fall handelt es sich um Methoden für das Singleton-Klassenobjekt. Sie können diesen Singleton dann mit einer neuen Klasse überschreiben, und die Methoden im vorherigen Klassenobjekt rufen die in der neuen Klasse definierten auf (richtig?). Wenn Sie also eine Methode im Kontext der ursprünglichen Klasse aufrufen, wird immer noch nur die ursprüngliche Statik ausgeführt. Wenn Sie jedoch eine Methode in der abgeleiteten Klasse aufrufen, werden Methoden entweder von der übergeordneten Klasse oder von der Unterklasse aufgerufen. Interessant und ich kann einen gewissen Wert darin sehen. Es braucht ein anderes Gedankenmuster.
Da Sie in Java arbeiten, müssen Sie sich an diese Vorgehensweise anpassen. Warum haben sie das getan? Nun, wahrscheinlich, um die Leistung zu diesem Zeitpunkt basierend auf der verfügbaren Technologie und dem verfügbaren Verständnis zu verbessern. Computersprachen entwickeln sich ständig weiter. Gehen Sie weit genug zurück und es gibt kein OOP. In Zukunft wird es weitere neue Ideen geben.
EDIT : Ein weiterer Kommentar. Jetzt, da ich die Unterschiede sehe und selbst Java / C # -Entwickler bin, kann ich verstehen, warum die Antworten, die Sie von Java-Entwicklern erhalten, verwirrend sein können, wenn Sie aus einer Sprache wie Ruby stammen. Java-
static
Methoden sind nicht mit Ruby-class
Methoden identisch . Java-Entwickler werden es schwer haben, dies zu verstehen, ebenso wie diejenigen, die hauptsächlich mit einer Sprache wie Ruby / Smalltalk arbeiten. Ich kann sehen, dass dies auch sehr verwirrend wäre, wenn Java auch "Klassenmethode" als eine andere Möglichkeit verwendet, um über statische Methoden zu sprechen, aber der gleiche Begriff wird von Ruby anders verwendet. Java verfügt nicht über Klassenmethoden im Ruby-Stil (sorry). Ruby verfügt nicht über statische Methoden im Java-Stil, die eigentlich nur alte prozedurale Stilfunktionen sind, wie in C zu finden.Übrigens - danke für die Frage! Ich habe heute etwas Neues über Klassenmethoden (Ruby-Stil) gelernt.
quelle
Nun ... die Antwort lautet NEIN, wenn Sie sich überlegen, wie sich eine Overriden-Methode in Java verhalten soll. Sie erhalten jedoch keinen Compilerfehler, wenn Sie versuchen, eine statische Methode zu überschreiben. Das heißt, wenn Sie versuchen zu überschreiben, hindert Java Sie nicht daran. Aber Sie erzielen sicherlich nicht den gleichen Effekt wie bei nicht statischen Methoden. Das Überschreiben in Java bedeutet einfach, dass die bestimmte Methode basierend auf dem Laufzeittyp des Objekts und nicht auf dem Kompilierungszeittyp des Objekts aufgerufen wird (was bei statischen Methoden zum Überschreiben der Fall ist). Okay ... irgendwelche Vermutungen aus dem Grund, warum sie sich seltsam verhalten? Da es sich um Klassenmethoden handelt und der Zugriff auf diese Methoden während der Kompilierungszeit immer nur unter Verwendung der Informationen zum Typ der Kompilierungszeit aufgelöst wird.
Beispiel : Versuchen wir zu sehen, was passiert, wenn wir versuchen, eine statische Methode zu überschreiben: -
Ausgabe : -
SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod
Beachten Sie die zweite Zeile der Ausgabe. Wäre die staticMethod überschrieben worden, hätte diese Zeile mit der dritten Zeile identisch sein müssen, da wir die 'staticMethod ()' für ein Objekt vom Typ Runtime als 'SubClass' und nicht als 'SuperClass' aufrufen. Dies bestätigt, dass die statischen Methoden immer nur anhand ihrer Informationen zum Kompilierungszeittyp aufgelöst werden.
quelle
Im Allgemeinen ist es nicht sinnvoll, statische Methoden zu überschreiben, da es keine gute Möglichkeit gibt, zu bestimmen, welche zur Laufzeit aufgerufen werden sollen. Wenn wir im Beispiel Employee RegularEmployee.getBonusMultiplier () aufrufen - welche Methode soll ausgeführt werden?
Im Fall von Java könnte man sich eine Sprachdefinition vorstellen, bei der es möglich ist, statische Methoden zu überschreiben, solange sie über eine Objektinstanz aufgerufen werden. Dies würde jedoch nur dazu führen, dass reguläre Klassenmethoden erneut implementiert werden, wodurch der Sprache Redundanz hinzugefügt wird, ohne dass dies wirklich von Vorteil ist.
quelle
Durch Überschreiben können wir abhängig vom Objekttyp eine polymorphe Natur erzeugen. Die statische Methode hat keine Beziehung zum Objekt. Daher kann Java das Überschreiben statischer Methoden nicht unterstützen.
quelle
Ich mag und verdopple Jays Kommentar ( https://stackoverflow.com/a/2223803/1517187 ).
Ich bin damit einverstanden, dass dies das schlechte Design von Java ist.
Viele andere Sprachen unterstützen das Überschreiben statischer Methoden, wie wir in früheren Kommentaren sehen. Ich habe das Gefühl, dass Jay wie ich auch von Delphi nach Java gekommen ist.
Delphi (Object Pascal) war die erste Sprache, die OOP implementierte.
Es ist offensichtlich, dass viele Menschen Erfahrung mit dieser Sprache hatten, da sie in der Vergangenheit die einzige Sprache war, die kommerzielle GUI-Produkte schrieb. Und - ja, wir könnten in Delphi statische Methoden überschreiben. Tatsächlich werden statische Methoden in Delphi als "Klassenmethoden" bezeichnet, während Delphi das andere Konzept der "statischen Delphi-Methoden" hatte, bei denen es sich um Methoden mit früher Bindung handelte. Um Methoden zu überschreiben, für die Sie eine späte Bindung verwenden mussten, deklarieren Sie die "virtuelle" Direktive. Es war also sehr praktisch und intuitiv und ich würde dies in Java erwarten.
quelle
Was nützt es, statische Methoden zu überschreiben? Sie können keine statischen Methoden über eine Instanz aufrufen.
BEARBEITEN: Es scheint, dass Sie durch ein unglückliches Versehen im Sprachdesign statische Methoden über eine Instanz aufrufen können . Im Allgemeinen macht das niemand. Mein Fehler.
quelle
variable.staticMethod()
, stattClass.staticMethod()
, wovariable
eine Variable mit deklarierten Typ istClass
. Ich bin damit einverstanden, dass es schlechtes Sprachdesign ist.Das Überschreiben in Java bedeutet einfach, dass die bestimmte Methode basierend auf dem Laufzeit-Typ des Objekts und nicht auf dem Typ zur Kompilierungszeit des Objekts aufgerufen wird (was bei überschriebenen statischen Methoden der Fall ist). Da statische Methoden Klassenmethoden sind, handelt es sich nicht um Instanzmethoden. Sie haben also nichts damit zu tun, welche Referenz auf welches Objekt oder welche Instanz verweist, da sie aufgrund der Art der statischen Methode zu einer bestimmten Klasse gehört. Sie können es in der Unterklasse neu deklarieren, aber diese Unterklasse weiß nichts über die statischen Methoden der übergeordneten Klasse, da es, wie gesagt, nur für die Klasse spezifisch ist, in der es deklariert wurde. Der Zugriff auf sie mithilfe von Objektreferenzen ist nur eine zusätzliche Freiheit, die von den Designern von Java eingeräumt wird, und wir sollten sicherlich nicht daran denken, diese Praxis nur dann zu beenden, wenn sie mehr Details und Beispiele einschränken http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html
quelle
Durch Überschreiben erreichen Sie einen dynamischen Polymorphismus. Wenn Sie statische Methoden überschreiben, sind die Wörter, die Sie verwenden möchten, widersprüchlich.
Statisch sagt - Kompilierungszeit, Überschreiben wird für dynamischen Polymorphismus verwendet. Beide sind von Natur aus gegensätzlich und können daher nicht zusammen verwendet werden.
Dynamisches polymorphes Verhalten tritt auf, wenn ein Programmierer ein Objekt verwendet und auf eine Instanzmethode zugreift. JRE ordnet verschiedene Instanzmethoden verschiedener Klassen zu, je nachdem, welche Art von Objekt Sie verwenden.
Wenn Sie statische Methoden überschreiben, greifen wir auf statische Methoden zu, indem wir den Klassennamen verwenden, der zur Kompilierungszeit verknüpft wird. Daher gibt es kein Konzept, Methoden zur Laufzeit mit statischen Methoden zu verknüpfen. Der Begriff "überschreibende" statische Methoden selbst hat also keine Bedeutung.
Hinweis: Selbst wenn Sie mit einem Objekt auf eine Klassenmethode zugreifen, ist der Java-Compiler intelligent genug, um dies herauszufinden, und führt statische Verknüpfungen durch.
quelle
Box.createBox
sinnvoller ist alsBoxFactory.createBox
und ein unvermeidbares Muster ist, wenn die Konstruktion ohne Ausnahmen einer Fehlerprüfung unterzogen werden muss (Konstruktoren können nicht fehlschlagen, sie können nur den Prozess / Wurf beenden Ausnahme), während eine statische Methode bei einem Fehler null zurückgeben oder sogar Erfolgs- / Fehlerrückrufe akzeptieren kann, um so etwas wie hastebin.com/codajahati.java zu schreiben .Die Antwort auf diese Frage ist einfach: Die als statisch gekennzeichnete Methode oder Variable gehört nur zur Klasse. Daher kann diese statische Methode nicht in die Unterklasse vererbt werden, da sie nur zur Superklasse gehört.
quelle
Einfache Lösung: Verwenden Sie eine Singleton-Instanz. Es ermöglicht Überschreibungen und Vererbung.
In meinem System habe ich die SingletonsRegistry-Klasse, die die Instanz für die übergebene Klasse zurückgibt. Wenn die Instanz nicht gefunden wird, wird sie erstellt.
Haxe Sprachkurs:
quelle
Singleton.get()
. Die Registrierung ist nur ein Boilerplate-Overhead und schließt GC für die Klassen aus.Eine statische Methode, Variable, Block oder verschachtelte Klasse gehört eher zur gesamten Klasse als zu einem Objekt.
Eine Methode in Java wird verwendet, um das Verhalten eines Objekts / einer Klasse verfügbar zu machen. Da die Methode statisch ist (dh die statische Methode wird nur zur Darstellung des Verhaltens einer Klasse verwendet), wird das Ändern / Überschreiben des Verhaltens der gesamten Klasse das Phänomen einer der Grundpfeiler der objektorientierten Programmierung, dh der hohen Kohäsion, verletzen . (Denken Sie daran, dass ein Konstruktor eine spezielle Methode in Java ist.)
Hoher Zusammenhalt - Eine Klasse sollte nur eine Rolle spielen. Zum Beispiel: Eine Fahrzeugklasse sollte nur Fahrzeugobjekte produzieren und keine Fahrräder, Lastwagen, Flugzeuge usw. Die Fahrzeugklasse kann jedoch einige Merkmale (Verhalten) aufweisen, die nur sich selbst gehören.
Daher beim Entwerfen der Java-Programmiersprache. Die Sprachdesigner dachten, Entwicklern zu erlauben, einige Verhaltensweisen einer Klasse für sich zu behalten, indem sie eine Methode statischer Natur machen.
Die unten Stück Code versucht , die statische Methode außer Kraft zu setzen, aber nicht alle Übersetzungsfehler auftreten.
Dies liegt daran, dass wir hier eine Methode nicht überschreiben, sondern sie nur neu deklarieren . Java ermöglicht die erneute Deklaration einer Methode (statisch / nicht statisch).
Das Entfernen des statischen Schlüsselworts aus der getVehileNumber () -Methode der Car-Klasse führt zu einem Kompilierungsfehler. Da wir versuchen, die Funktionalität der statischen Methode zu ändern, die nur zur Vehicle-Klasse gehört.
Wenn getVehileNumber () als final deklariert wird, wird der Code nicht kompiliert, da das Schlüsselwort final den Programmierer daran hindert , die Methode erneut zu deklarieren.
Insgesamt liegt es an den Software-Designern, wo die statischen Methoden angewendet werden sollen. Ich persönlich bevorzuge statische Methoden, um einige Aktionen auszuführen, ohne eine Instanz einer Klasse zu erstellen. Zweitens, um das Verhalten einer Klasse vor der Außenwelt zu verbergen.
quelle
Hier ist eine einfache Erklärung. Eine statische Methode ist einer Klasse zugeordnet, während eine Instanzmethode einem bestimmten Objekt zugeordnet ist. Überschreibungen ermöglichen das Aufrufen der unterschiedlichen Implementierung der überschriebenen Methoden, die dem jeweiligen Objekt zugeordnet sind. Es ist daher nicht intuitiv, statische Methoden zu überschreiben, die nicht einmal Objekten zugeordnet sind, sondern in erster Linie der Klasse selbst. Daher können statische Methoden nicht basierend auf dem aufrufenden Objekt überschrieben werden. Sie werden immer der Klasse zugeordnet, in der sie erstellt wurden.
quelle
public abstract IBox createBox();
interne IBox-Oberfläche zu haben? Box kann IBox implementieren, um createBox zu überschreiben, und die Erstellung eines Objekts führt zu einer gültigen IBox, andernfalls wird eine Null zurückgegeben. Konstruktoren können nicht "null" zurückgeben, und daher sind Sie gezwungen, (1) ÜBERALL Ausnahmen zu verwenden (was wir jetzt tun) oder (2) Factory-Klassen zu erstellen, die das tun, was ich zuvor gesagt habe, aber für Anfänger oder Experten keinen Sinn ergeben von Java (was wir jetzt auch tun). Statische nicht implementierte Methoden lösen dies.Wenn man nun die obigen Antworten sieht, weiß jeder, dass wir statische Methoden nicht überschreiben können, aber man sollte das Konzept des Zugriffs auf statische Methoden aus der Unterklasse nicht missverstehen .
Zum Beispiel siehe folgenden Code: -
Ausgabe:-
Vielen Dank
quelle
Der folgende Code zeigt, dass es möglich ist:
quelle
osm
istOverridenStaticMeth
nichtOverrideStaticMeth
.