Warum können statische Methoden nur statische Daten verwenden?
38
Ich verstehe nicht, warum eine statische Methode keine nicht statischen Daten verwenden kann. Kann jemand erklären, was die Probleme sind und warum wir das nicht können?
Weil aus Sicht statischer Methoden nur statische Daten existieren.
Mouviciel
4
Das Teilen Ihrer Forschung hilft allen. Sagen Sie uns, was Sie versucht haben und warum es nicht Ihren Bedürfnissen entsprach. Dies zeigt, dass Sie sich die Zeit genommen haben, um sich selbst zu helfen, es erspart uns, offensichtliche Antworten zu wiederholen, und vor allem hilft es Ihnen, eine spezifischere und relevantere Antwort zu erhalten. Siehe auch Wie man fragt
Mücke
19
@gnat in diesem Fall versucht OP, den Grund für eine Entwurfsentscheidung zu verstehen. Was soll er in diesem Fall versuchen?
Geek
2
@Geek - das Vorhandensein statischer Methoden, statischer Daten ist ein Problem beim Sprachdesign. Unter der Annahme von Standardbedeutungen ist dies nicht der Fall, wenn statische Methoden nicht auf Instanzdaten zugreifen können. Die Einschränkung ergibt sich aus den Definitionen und dem, was möglich und sinnvoll ist, und nicht aus den Schwächen einiger Sprachdesigner.
Steve314
6
„Es gibt keine: Gertrude Stein paraphrasieren diese dort.“
Nilpferd-Tänzer
Antworten:
73
Wenn Sie in den meisten OO-Sprachen eine Methode in einer Klasse definieren, wird diese zu einer Instanzmethode . Wenn Sie über das Schlüsselwort eine neue Instanz dieser Klasse erstellen new, initialisieren Sie einen neuen Datensatz, der nur für diese Instanz eindeutig ist. Die zu dieser Instanz gehörenden Methoden können dann mit den darauf definierten Daten arbeiten.
Dagegen kennen statische Methoden einzelne Klasseninstanzen nicht. Die statische Methode ähnelt einer freien Funktion in C oder C ++. Es ist nicht an eine bestimmte Instanziierung der Klasse gebunden. Aus diesem Grund können sie nicht auf Instanzwerte zugreifen. Es gibt keine Instanz, der man einen Wert entnehmen könnte!
Statische Daten ähneln einer statischen Methode. Einem deklarierten Wert ist statickeine Instanz zugeordnet. Es existiert für jede Instanz und wird nur an einer einzigen Stelle im Speicher deklariert. Wenn es jemals geändert wird, wird es für jede Instanz dieser Klasse geändert.
Eine statische Methode kann auf statische Daten zugreifen, da beide unabhängig von bestimmten Instanzen einer Klasse existieren.
Es kann hilfreich sein, sich anzusehen, wie Sie eine statische Methode im Vergleich zu einer Instanzmethode aufrufen. Angenommen, wir hatten die folgende Klasse (mit Java-ähnlichem Pseudocode):
classFoo{// This static value belongs to the class Foopublicstaticfinal string name ="Foo";// This non-static value will be unique for every instanceprivateint value;publicFoo(int value){this.value = value;}publicvoid sayValue(){
println("Instance Value: "+ value);}publicstaticvoid sayName(){
println("Static Value: "+ name);}}Foo foo1 =newFoo(10);Foo foo2 =newFoo(20);
foo1.sayValue();// Prints "Instance Value: 10" - called on foo1
foo2.sayValue();// Prints "Instance Value: 20" - called on foo2Foo.sayName();// Prints "Static Value: Foo" - called on Foo (not foo1 or foo2)
Aktualisieren
Wie KOMMT heraus in den Kommentaren Punkte, eine statische Methode ist die Lage , die Arbeit mit nicht-statischen Daten, aber es muss explizit übergeben werden. Nehmen wir an, die FooKlasse hatte eine andere Methode:
Addist immer noch statisch und hat keine eigenen valueInstanzen. Als Mitglied der Klasse Foo kann es jedoch auf die privaten valueFelder der übergebenen foo1und der foo2Instanzen zugreifen . In diesem Fall verwenden wir es, um ein neuesFoo mit den hinzugefügten Werten der beiden übergebenen Werte zurückzugeben.
Foo foo3 =Foo.Add(foo1, foo2);// creates a new Foo with a value of 30
Erweitern von "Es gibt keine Instanz, aus der ein Wert entnommen werden kann" - selbst wenn es Instanzen gibt, kann die statische Methode nicht wissen, aus welcher Instanz ein Wert entnommen werden soll.
Steve314
9
Dies ist in Sprachen, die nicht standardmäßig alle Elemente eines Objekts erfordern, viel einfacher zu erklären.
Mason Wheeler
3
@Mason Wahre Worte. Sprachen wie Java erzwingen eine falsche Vorstellung, dass eine Funktion etwas ist, das notwendigerweise zu einer Klasse gehört.
KChaloux
5
Dies ist eine gute Antwort, aber sie sagt immer noch nicht die ganze Wahrheit: Statische Methoden können auf nicht statische Daten zugreifen. Sie haben einfach nicht das implizite Objekt oder die implizite thisReferenz verfügbar. Ich denke, das ist lebenswichtig zu verstehen.
KOMMEN SIE VOM
2
@COMEFROM Du meinst mit explizitem Übergeben? Ich kann es notieren, wenn ich Sie richtig verstehe. Ich nahm an, dass impliziert wurde, dass eine statische Methode auf explizit übergebene nicht statische Daten zugreifen kann, da jede Funktion mit Daten arbeiten kann, die explizit an sie übergeben wurden.
KChaloux
22
Erklären wir es mit einer hypothetischen Stichprobe.
Stellen Sie sich eine einfache Klasse vor:
classUser{User(string n){ name = n;};
string name;}
Denken Sie jetzt - was ist, wenn wir dem Benutzer eine neue statische Methode hinzufügen, zB:
static string GetName();
und du nennst es:
string x =User::GetName()
was würde x enthalten? "Jim", "Bones" oder etwas anderes?
Das Problem ist, dass eine statische Methode eine einzelne Methode ist, die für die Klasse und nicht für die Objekte definiert ist. Infolgedessen wissen Sie nicht, für welches Objekt es gelten könnte. Deshalb ist es eine besondere Sache. Es ist am besten, sich statische Methoden als einzelne Dinge vorzustellen, wie zum Beispiel Funktionen in C. Dass Sprachen wie Java sie in Klassen enthalten haben, ist hauptsächlich ein Problem, da Java es nicht zulässt, dass etwas außerhalb einer Klasse existiert. Daher müssen Funktionen wie diese in irgendeiner Weise in einer Klasse erzwungen werden (ein bisschen wie main () auch in einer Klasse, wenn alle Vernunft sagt, dass es eine singuläre, eigenständige Funktion sein soll).
Nicht statische Daten sind einer Instanz der Klasse zugeordnet. Statische Methoden (und Daten) sind keiner bestimmten Instanz der Klasse zugeordnet. Es muss keine Instanz einer Klasse vorhanden sein, um statische Methoden verwenden zu können. Selbst wenn es Instanzen gäbe, könnte Java nicht garantieren, dass Sie auf der erwarteten Instanz arbeiten, wenn Sie eine statische Methode aufrufen. Daher können statische Methoden nicht auf nicht statische Daten zugreifen.
Es kann Felddaten verwenden; Betrachten Sie den folgenden Java-Code:
classMyBean{privateString myString;staticvoid myStaticMethod(){
myString ="tada";/*not allowed; if this was possible how would
be different from a field without static?*/MyBean myBean =newMyBean();//allowed if associated with an instance
myBean.myString ="tada";}}
Dies kann technisch gesehen eine statische Methode sein, bei der nicht statische Daten verwendet werden. Natürlich können Sie eine neue Instanz erstellen und darauf zugreifen. Aber das hat überhaupt nichts mit staticNess zu tun .
Bobson
2
Eigentlich denke ich, dass dies eine sehr gute Ergänzung zur Erläuterung des Punktes ist. Sie hebt den Punkt hervor, dass die statische Methode eine Instanz der Klasse benötigt, bevor sie auf nicht statische Daten zugreifen kann, und liefert einen intuitiven Grund, warum dies so ist.
Ben Hocking
@ Bobson Sie sollten den Code und die Kommentare auch lesen.
m3th0dman
@BenHocking "Ja", auch wenn ich denke, es ist gut zu sagen, dass "Instanzvariable immer mit Objekt verknüpft ist"
JAVA
2
Ich denke, hier geht es um Verständnis.
Aus technischer Sicht ist eine statische Methode, die aus einem Objekt aufgerufen wird, durchaus in der Lage, die Instanzfelder anzuzeigen. Ich vermute sehr, dass dies der Grund für die Frage war.
Das Problem ist, dass Methoden von außerhalb des Objekts aufgerufen werden können. Zu diesem Zeitpunkt gibt es keine Instanzdaten, um sie bereitzustellen - und daher keine Möglichkeit für den Compiler, den Code aufzulösen. Da das Zulassen von Instanzdaten einen Widerspruch verursachte, dürfen wir keine Instanzdaten zulassen.
Ich stimme dir nicht zu. Eine statische Methode kann nicht auf Instanzdaten zugreifen, da auf Instanzdaten über eine Instanz des Objekts zugegriffen werden muss und die statische Methode keiner bestimmten Instanz (sondern der Klassendefinition) zugeordnet ist.
Phill W.
Du vermisst meinen Standpunkt. Wenn es aus der Klasse aufgerufen wird, kann der Compiler einen Instanzzeiger übergeben, wie es der Fall ist, wenn es keine statische Klasse ist. Das Problem tritt auf, wenn es von einem anderen Ort aufgerufen wird - was bedeutet, dass private statische Methoden auf
Instanzdaten
Ja, der Compiler / könnte / aber warum sollte er? Das Übergeben eines solchen Zeigers reduziert ihn im Wesentlichen auf eine Instanzmethode. Ihre Behauptung, dass dies nur mit privaten Methoden möglich ist, ist umstritten - Reflektionstechnologien machen / all / Methoden zugänglich - privat oder nicht - was dies zu einer noch riskanteren Angelegenheit macht. Unsere Freunde in Redmond sind in die andere Richtung gegangen; Ihre Sprachen geben eine Warnung aus, wenn Sie versuchen, eine statische Methode für eine Objektinstanz (und nicht für die Klasse selbst) aufzurufen.
Phill W.
1
Stellen Sie es sich als statische Methoden vor, die in einer nicht objektorientierten Dimension leben.
In der "objektorientierten Dimension" kann eine Klasse mehrere Ichs (Instanzen) hervorbringen, jedes Ich hat über seinen Zustand ein Gewissen von sich.
In der flachen Nicht-OO-Dimension vergisst eine Klasse, dass ihr Ego in der OO-Dimension lebt. Ihre Welt ist flach und prozedural, fast so, als wäre OOP noch nicht erfunden worden, und als wäre die Klasse ein kleines prozedurales Programm, und die statischen Daten wären nur globale Variablen.
Ich denke, der einfachste Weg, dies zu erklären, besteht darin, sich einen Code anzusehen und dann zu überlegen, welche Ergebnisse der Code erwarten würde.
// Create three new cars. Cars have a name attribute. Car car1 =newCar("Mazda3");Car car2 =newCar("FordFocus");Car car3 =newCar("HondaFit");// Now we would like to print the names of some cars: // First off why don't we try this: Car.printCarName();// Expected behaviour: // If we think about what we are trying to do here it doesn't// really make sense. What instance of car name should this // print? Should it print Mazda3? FordFoucs?// What is the expected behaviour? If we are going to have a// static call on car call printCarName it should probably do// something like print all car names or a random car name or// throw an error. //Now lets try this instead: Car.printCarName(car1);// Expected Behaviour: // Luckily the expected behaviour is very clear here. This// should print Mazda3. This works as expected. // Finally lets try this:
car1.printMyName();// Expected Behaviour:// Same as previous example, however this is the *right* way// to do it.
Der Vollständigkeit halber ist hier die Fahrzeugklasse:
publicclassCar{publicString name;publicCar(String name){this.name = name;}publicstatic printCarName(){
print "Not sure what to do here... Don't know which car you are talking about.";}publicstatic printCarName(Car c){
print c.name;}public/*NOT static*/ printMyName(){
print this.name;}}
@gnat Aktualisiert mit Kommentaren zur Verdeutlichung.
Sixtyfootersdude
1
Die anderen Antworten sagen so ziemlich alles, aber es gibt einige "Details", die ich hinzufügen möchte.
Bei statischen Methoden (beispielsweise in Java) ist kein implizites Objekt zugeordnet (über das zugegriffen werden kann this), auf dessen Mitglieder Sie normalerweise direkt über den Namen zugreifen können.
Das bedeutet nicht, dass sie nicht auf statische Daten zugreifen können.
classMyClass{publicstaticvoid foo(MyOtherClass object){System.out.println(object.member);}} classMyOtherClass{publicint member =10;}
Ich weiß, dass dies nur ein Detail ist, aber ich fand Ihre Frage seltsam, als ich sie las. "Kann nur statische Daten verwenden" ist zu restriktiv.
Ich habe den Code übrigens nicht getestet, sondern nur hier geschrieben, um zu veranschaulichen, was ich gesagt habe.
Antworten:
Wenn Sie in den meisten OO-Sprachen eine Methode in einer Klasse definieren, wird diese zu einer Instanzmethode . Wenn Sie über das Schlüsselwort eine neue Instanz dieser Klasse erstellen
new
, initialisieren Sie einen neuen Datensatz, der nur für diese Instanz eindeutig ist. Die zu dieser Instanz gehörenden Methoden können dann mit den darauf definierten Daten arbeiten.Dagegen kennen statische Methoden einzelne Klasseninstanzen nicht. Die statische Methode ähnelt einer freien Funktion in C oder C ++. Es ist nicht an eine bestimmte Instanziierung der Klasse gebunden. Aus diesem Grund können sie nicht auf Instanzwerte zugreifen. Es gibt keine Instanz, der man einen Wert entnehmen könnte!
Statische Daten ähneln einer statischen Methode. Einem deklarierten Wert ist
static
keine Instanz zugeordnet. Es existiert für jede Instanz und wird nur an einer einzigen Stelle im Speicher deklariert. Wenn es jemals geändert wird, wird es für jede Instanz dieser Klasse geändert.Eine statische Methode kann auf statische Daten zugreifen, da beide unabhängig von bestimmten Instanzen einer Klasse existieren.
Es kann hilfreich sein, sich anzusehen, wie Sie eine statische Methode im Vergleich zu einer Instanzmethode aufrufen. Angenommen, wir hatten die folgende Klasse (mit Java-ähnlichem Pseudocode):
Aktualisieren
Wie KOMMT heraus in den Kommentaren Punkte, eine statische Methode ist die Lage , die Arbeit mit nicht-statischen Daten, aber es muss explizit übergeben werden. Nehmen wir an, die
Foo
Klasse hatte eine andere Methode:Add
ist immer noch statisch und hat keine eigenenvalue
Instanzen. Als Mitglied der Klasse Foo kann es jedoch auf die privatenvalue
Felder der übergebenenfoo1
und derfoo2
Instanzen zugreifen . In diesem Fall verwenden wir es, um ein neuesFoo
mit den hinzugefügten Werten der beiden übergebenen Werte zurückzugeben.quelle
this
Referenz verfügbar. Ich denke, das ist lebenswichtig zu verstehen.Erklären wir es mit einer hypothetischen Stichprobe.
Stellen Sie sich eine einfache Klasse vor:
Jetzt erstellen wir 2 Instanzen dieser Klasse:
Denken Sie jetzt - was ist, wenn wir dem Benutzer eine neue statische Methode hinzufügen, zB:
und du nennst es:
was würde x enthalten? "Jim", "Bones" oder etwas anderes?
Das Problem ist, dass eine statische Methode eine einzelne Methode ist, die für die Klasse und nicht für die Objekte definiert ist. Infolgedessen wissen Sie nicht, für welches Objekt es gelten könnte. Deshalb ist es eine besondere Sache. Es ist am besten, sich statische Methoden als einzelne Dinge vorzustellen, wie zum Beispiel Funktionen in C. Dass Sprachen wie Java sie in Klassen enthalten haben, ist hauptsächlich ein Problem, da Java es nicht zulässt, dass etwas außerhalb einer Klasse existiert. Daher müssen Funktionen wie diese in irgendeiner Weise in einer Klasse erzwungen werden (ein bisschen wie main () auch in einer Klasse, wenn alle Vernunft sagt, dass es eine singuläre, eigenständige Funktion sein soll).
quelle
Nicht statische Daten sind einer Instanz der Klasse zugeordnet. Statische Methoden (und Daten) sind keiner bestimmten Instanz der Klasse zugeordnet. Es muss keine Instanz einer Klasse vorhanden sein, um statische Methoden verwenden zu können. Selbst wenn es Instanzen gäbe, könnte Java nicht garantieren, dass Sie auf der erwarteten Instanz arbeiten, wenn Sie eine statische Methode aufrufen. Daher können statische Methoden nicht auf nicht statische Daten zugreifen.
quelle
Es kann Felddaten verwenden; Betrachten Sie den folgenden Java-Code:
quelle
static
Ness zu tun .Ich denke, hier geht es um Verständnis.
Aus technischer Sicht ist eine statische Methode, die aus einem Objekt aufgerufen wird, durchaus in der Lage, die Instanzfelder anzuzeigen. Ich vermute sehr, dass dies der Grund für die Frage war.
Das Problem ist, dass Methoden von außerhalb des Objekts aufgerufen werden können. Zu diesem Zeitpunkt gibt es keine Instanzdaten, um sie bereitzustellen - und daher keine Möglichkeit für den Compiler, den Code aufzulösen. Da das Zulassen von Instanzdaten einen Widerspruch verursachte, dürfen wir keine Instanzdaten zulassen.
quelle
Stellen Sie es sich als statische Methoden vor, die in einer nicht objektorientierten Dimension leben.
In der "objektorientierten Dimension" kann eine Klasse mehrere Ichs (Instanzen) hervorbringen, jedes Ich hat über seinen Zustand ein Gewissen von sich.
In der flachen Nicht-OO-Dimension vergisst eine Klasse, dass ihr Ego in der OO-Dimension lebt. Ihre Welt ist flach und prozedural, fast so, als wäre OOP noch nicht erfunden worden, und als wäre die Klasse ein kleines prozedurales Programm, und die statischen Daten wären nur globale Variablen.
quelle
Ich denke, der einfachste Weg, dies zu erklären, besteht darin, sich einen Code anzusehen und dann zu überlegen, welche Ergebnisse der Code erwarten würde.
Der Vollständigkeit halber ist hier die Fahrzeugklasse:
quelle
Die anderen Antworten sagen so ziemlich alles, aber es gibt einige "Details", die ich hinzufügen möchte.
Bei statischen Methoden (beispielsweise in Java) ist kein implizites Objekt zugeordnet (über das zugegriffen werden kann
this
), auf dessen Mitglieder Sie normalerweise direkt über den Namen zugreifen können.Das bedeutet nicht, dass sie nicht auf statische Daten zugreifen können.
Ich weiß, dass dies nur ein Detail ist, aber ich fand Ihre Frage seltsam, als ich sie las. "Kann nur statische Daten verwenden" ist zu restriktiv.
Ich habe den Code übrigens nicht getestet, sondern nur hier geschrieben, um zu veranschaulichen, was ich gesagt habe.
quelle