Das new
Schlüsselwort in Sprachen wie Java, Javascript und C # erstellt eine neue Instanz einer Klasse.
Diese Syntax scheint von C ++ geerbt worden zu sein, wo new
speziell eine neue Instanz einer Klasse auf dem Heap zugeordnet und ein Zeiger auf die neue Instanz zurückgegeben wird. In C ++ ist dies nicht die einzige Möglichkeit, ein Objekt zu erstellen. Sie können auch ein Objekt auf dem Stapel erstellen, ohne new
- zu verwenden, und tatsächlich ist diese Art der Erstellung von Objekten in C ++ weitaus üblicher.
Aus einem C ++ - Hintergrund stammend, new
erschien mir das Schlüsselwort in Sprachen wie Java, Javascript und C # natürlich und offensichtlich. Dann fing ich an, Python zu lernen, das das new
Schlüsselwort nicht hat . In Python wird eine Instanz einfach durch Aufrufen des Konstruktors wie folgt erstellt:
f = Foo()
Anfangs schien mir das ein bisschen abwegig zu sein, bis mir klar wurde, dass es für Python keinen Grund gibt new
, weil alles ein Objekt ist und man nicht zwischen verschiedenen Konstruktorsyntaxen unterscheiden muss.
Aber dann dachte ich mir - worum geht es eigentlich new
in Java? Warum sollten wir sagen Object o = new Object();
? Warum nicht einfach Object o = Object();
? In C ++ ist dies definitiv erforderlich new
, da zwischen Zuweisung auf dem Heap und Zuweisung auf dem Stack unterschieden werden muss, in Java jedoch alle Objekte auf dem Heap erstellt werden. Warum also überhaupt das new
Schlüsselwort? Dieselbe Frage könnte für Javascript gestellt werden. In C #, mit dem ich weniger vertraut bin, new
kann es meiner Meinung nach sinnvoll sein, zwischen Objekttypen und Werttypen zu unterscheiden, aber ich bin mir nicht sicher.
Unabhängig davon scheint es mir, dass viele Sprachen, die nach C ++ kamen, das new
Schlüsselwort einfach "geerbt" haben - ohne es wirklich zu brauchen. Es ist fast wie ein Schlagwort . Wir scheinen es aus keinem Grund zu brauchen, und doch ist es da.
Frage: Habe ich diesbezüglich Recht? Oder gibt es einen zwingenden Grund, new
der in C ++ inspirierten speicherverwalteten Sprachen wie Java, Javascript und C # liegen muss, aber nicht in Python?
quelle
new
Schlüsselwort hat. Natürlich möchte ich einen neuen variablen, blöden Compiler erstellen! Eine gute Sprache wäre meiner Meinung nach einer Syntax wief = heap Foo()
,f = auto Foo()
.f
die Funktion nicht verlassen wird, wird Stapelspeicher zugewiesen.f
wenn die umschließende Funktion zurückkehrt.Antworten:
Ihre Beobachtungen sind richtig. C ++ ist ein kompliziertes Biest, und das
new
Schlüsselwort wurde verwendet, um zwischen etwas zu unterscheiden, dasdelete
später benötigt wurde, und etwas, das automatisch zurückgefordert werden würde. In Java und C # haben sie dasdelete
Schlüsselwort gelöscht, weil der Garbage Collector es für Sie erledigen würde.Das Problem ist dann, warum sie das
new
Schlüsselwort behalten haben ? Ohne mit den Leuten zu sprechen, die die Sprache geschrieben haben, ist es schwierig zu antworten. Meine besten Vermutungen sind unten aufgeführt:new
Schlüsselwort ein Objekt auf dem Heap erstellt. Warum also das erwartete Verhalten ändern?Ruby ist irgendwo zwischen Python und Java / C # in seiner Verwendung
new
. Grundsätzlich instanziieren Sie ein Objekt wie folgt:Es ist kein Schlüsselwort, sondern eine statische Methode für die Klasse. Dies bedeutet, dass Sie, wenn Sie einen Singleton wünschen, die Standardimplementierung von überschreiben können, um
new()
jedes Mal dieselbe Instanz zurückzugeben. Es ist nicht unbedingt zu empfehlen, aber es ist möglich.quelle
alloc
Methode (ungefähr die gleiche wie die von Ruby'snew
) ebenfalls nur eine Klassenmethode.Kurz, Sie haben recht. Das Schlüsselwort new ist in Sprachen wie Java und C # überflüssig. Hier einige Einblicke von Bruce Eckel, der 1990 Mitglied des C ++ Standard Comitee war und später Bücher über Java veröffentlichte: http://www.artima.com/weblogs/viewpost.jsp?thread=260578
quelle
var
Schlüsselwort ist bei weitem nicht so gut wieauto
in C ++, aber ich hoffe, es wird sich verbessern.Ich kann mir zwei Gründe vorstellen:
new
unterscheidet zwischen einem Objekt und einem Primitivnew
Syntax ist etwas besser lesbar (IMO)Der erste ist trivial. Ich glaube nicht, dass es schwieriger ist, die beiden so oder so auseinander zu halten. Die zweite ist ein Beispiel für den Punkt des OP,
new
der redundant ist.Es kann jedoch zu Namespace-Konflikten kommen. Erwägen:
Sie könnten, ohne zu viel Vorstellungskraft, leicht zu einem unendlich rekursiven Aufruf kommen. Der Compiler müsste den Fehler "Funktionsname wie Objekt" erzwingen. Das würde wirklich nicht schaden, aber es ist viel einfacher zu benutzen
new
, was besagt, dassGo to the object of the same name as this method and use the method that matches this signature.
Java eine sehr einfach zu analysierende Sprache ist, und ich vermute, dass dies in diesem Bereich hilfreich ist.quelle
Java, für einen, hat immer noch die Dichotomie von C ++: nicht ganz alles ein Objekt ist. Java verfügt über integrierte Typen (z. B.
char
undint
), die nicht dynamisch zugewiesen werden müssen.Dies bedeutet jedoch nicht, dass
new
dies in Java wirklich notwendig ist - die Menge der Typen, die nicht dynamisch zugewiesen werden müssen, ist fest und bekannt. Wenn Sie ein Objekt definieren, weiß der Compiler möglicherweise (und tatsächlich), ob es sich um einen einfachen Wert handeltchar
oder um ein Objekt, das dynamisch zugewiesen werden muss.Ich werde (noch einmal) davon Abstand nehmen, darüber zu urteilen, was dies für die Qualität von Javas Design bedeutet (oder, je nachdem, dessen Fehlen).
quelle
new
, das ist also nicht wirklich der Grund.In JavaScript benötigen Sie es, da der Konstruktor wie eine normale Funktion aussieht. Woher sollte JS wissen, dass Sie ein neues Objekt erstellen möchten, wenn das neue Schlüsselwort nicht vorhanden ist?
quelle
Interessanterweise VB tut es brauchen - die Unterscheidung zwischen
deklariert eine Variable, ohne sie zuzuweisen, das Äquivalent von
Foo f;
in C # undDas Deklarieren der Variablen und Zuweisen einer neuen Instanz der Klasse, die der
var f = new Foo();
in C # entspricht, ist eine wesentliche Unterscheidung. In pre-.NET VB konnten Sie sogarDim f As Foo
oder verwenden,Dim f As New Foo
da Konstruktoren nicht überlastet wurden.quelle
Dim f As Foo()
deklariert ein Array vonFoo
s. Oh Freude! :-)Dim Foo As New Bar
würde effektivFoo
eine Eigenschaft erstellt, die a erstellt,Bar
wenn es während (ieNothing
) gelesen wurde . Dieses Verhalten war nicht auf ein einziges Mal beschränkt. Setzen SieFoo
aufNothing
und lesen Sie es dann, um eine weitere neue zu erstellenBar
.Ich mag viele Antworten und möchte Folgendes hinzufügen:
Es erleichtert das Lesen von Code.
Nicht, dass diese Situation häufig vorkommt, aber Sie möchten eine Methode im Namen eines Verbs, das denselben Namen wie ein Substantiv hat. C # und andere Sprachen haben natürlich das Wort
object
reserviert. Wäre dies nicht derFoo = object()
Fall, wäre dies das Ergebnis des Objektmethodenaufrufs oder würde ein neues Objekt instanziiert. Es ist zu hoffen, dass die Sprache ohne dasnew
Schlüsselwort Schutz vor dieser Situation bietet. Wenn Sie jedoch dasnew
Schlüsselwort vor dem Aufruf eines Konstruktors benötigen, können Sie die Existenz einer Methode zulassen, die denselben Namen wie ein Objekt hat.quelle
In vielen Programmiersprachen gibt es eine Menge Überbleibsel. Manchmal ist es beabsichtigt da (C ++ wurde entwickelt, um mit C so kompatibel wie möglich zu sein), manchmal ist es einfach da. Betrachten Sie für ein ungeheuerlicheres Beispiel, wie weit sich die gebrochene C-
switch
Anweisung verbreitet hat.Ich kenne Javascript und C # nicht gut genug, um es zu sagen, aber ich sehe keinen Grund für
new
Java, außer dass C ++ es hatte.quelle
x = new Y()
in JavaScript nicht instanziiert dieY
Klasse, weil kein JavaScript haben Klassen. Aber es sieht aus wie Java, also überträgt es dasnew
Schlüsselwort von Java, was es natürlich von C ++ weiterleitet.In C # können Typen in Kontexten angezeigt werden, in denen sie ansonsten von einem Member verdeckt werden könnten. Mit können Sie eine Eigenschaft mit demselben Namen wie den Typ haben. Folgendes berücksichtigen,
Beachten Sie die Verwendung von
new
, um zu verdeutlichen, dassAddress
es sich bei demAddress
Typ nicht um dasAddress
Mitglied handelt. Auf diese Weise kann ein Mitglied denselben Namen wie sein Typ haben. Ohne dies müssten Sie dem Namen des Typs ein Präfix voranstellen, um die Namenskollision zu vermeiden, zCAddress
. Dies war sehr beabsichtigt, da Anders die ungarische Notation oder ähnliches nie mochte und wollte, dass C # ohne sie verwendet werden kann. Die Tatsache, dass es auch bekannt war, war ein doppelter Bonus.quelle
Interessanterweise ist mit dem Aufkommen der perfekten Weiterleitung das Nicht-Platzieren auch
new
in C ++ überhaupt nicht erforderlich. Es wird also wohl in keiner der genannten Sprachen mehr benötigt.quelle
std::shared_ptr<int> foo();
anrufen müssennew int
.Ich bin mir nicht sicher, ob Java-Designer dies im Auge hatten, aber wenn Sie sich Objekte als rekursive Datensätze vorstellen, können Sie sich vorstellen, dass
Foo(123)
dies kein Objekt zurückgibt, sondern eine Funktion, deren Fixpunkt das zu erstellende Objekt ist (dh eine Funktion, die zurückkehren würde) das Objekt, wenn es als Argument angegeben ist). Und der Zweck vonnew
ist, "den Knoten zu binden" und diesen Fixpunkt zurückzugeben. Mit anderen Worten,new
würde das "Objekt-zu-sein" dessen bewusst machenself
.Diese Art der Vorgehensweise kann zum Beispiel bei der Formalisierung der Vererbung hilfreich sein: Sie können eine Objektfunktion mit einer anderen Objektfunktion erweitern und diese schließlich
self
mithilfe dernew
folgenden Methoden gemeinsam bereitstellen :Hier werden
&
zwei Objektfunktionen kombiniert.In diesem Fall
new
könnte definiert werden als:quelle
Null zulassen.
Neben der Heap-basierten Zuweisung hat Java die Verwendung von Null-Objekten übernommen. Nicht nur als Artefakt, sondern als Feature. Wenn Objekte den Status Null haben können, müssen Sie die Deklaration von der Initialisierung trennen. Daher das neue Schlüsselwort.
In C ++ eine Zeile wie
Würde sofort den Standardkonstruktor aufrufen.
quelle
Person me = Nil
oderPerson me
Nil zu haben undPerson me = Person()
für Nicht-Nil zu verwenden? Mein Punkt ist, dass es nicht so aussieht, als ob Nil ein Faktor bei dieser Entscheidung war ...Person me
wenn Sie null sind undPerson me()
den Standardkonstruktor aufrufen. Sie brauchen also immer Klammern, um irgendetwas aufzurufen und so eine C ++ - Unregelmäßigkeit zu beseitigen.Der Grund, warum Python es nicht benötigt, liegt an seinem Typsystem. Grundsätzlich spielt es
foo = bar()
in Python keine Rolle, obbar()
eine Methode aufgerufen, eine Klasse instanziiert oder ein Funktionsobjekt ist. In Python gibt es keinen grundlegenden Unterschied zwischen einem Funktor und einer Funktion (da Methoden Objekte sind). und man könnte sogar argumentieren, dass eine instanziierte Klasse ein Sonderfall eines Funktors ist. Daher gibt es keinen Grund, einen künstlichen Unterschied im Geschehen zu schaffen (zumal die Speicherverwaltung in Python so extrem verborgen ist).In einer Sprache mit einem anderen Typensystem oder in der Methoden und Klassen keine Objekte sind, besteht die Möglichkeit eines stärkeren konzeptionellen Unterschieds zwischen dem Erstellen eines Objekts und dem Aufrufen einer Funktion oder eines Funktors. Selbst wenn der Compiler / Interpreter das
new
Schlüsselwort nicht benötigt , ist es verständlich, dass es in Sprachen verwaltet wird, die nicht alle Grenzen von Python überschreiten.quelle
Tatsächlich gibt es in Java einen Unterschied bei der Verwendung von Strings:
unterscheidet sich von
Angenommen, der String
"myString"
wurde noch nie zuvor verwendet, erstellt die erste Anweisung ein einzelnes String-Objekt im String-Pool (einem speziellen Bereich des Heap-Speichers), während die zweite Anweisung zwei Objekte erstellt, eines im normalen Heap-Bereich für Objekte und eines im String-Pool . Es ist ziemlich offensichtlich, dass die zweite Aussage in diesem speziellen Szenario nutzlos ist, aber von der Sprache zugelassen wird.Dies bedeutet, dass new sicherstellt, dass das Objekt in diesem speziellen Bereich des Heaps erstellt wird, der für die normale Objektinstanziierung reserviert ist. Es gibt jedoch auch andere Möglichkeiten, Objekte ohne diesen Bereich zu instanziieren. Das obige Beispiel ist ein Beispiel, und es ist noch Raum für Erweiterbarkeit vorhanden.
quelle
String myString = String("myString");
?" (Beachten Sie das Fehlen desnew
Schlüsselworts)class MyClass { public MyClass() {} public MyClass MyClass() {return null;} public void doSomething { MyClass myClass = MyClass();}} //which is it, constructor or method?
String
gegen Java-Konventionen, sodass Sie davon ausgehen können, dass jede Methode, die mit Großbuchstaben beginnt, ein Konstruktor ist. Und zweitens, wenn wir nicht durch Java eingeschränkt sind, hat Scala "case classes", bei denen der Konstruktor genau so aussieht, wie ich es gesagt habe. Wo liegt also das Problem?new
für verwaltete Sprachen . Ich habe gezeigt, dass dies überhauptnew
nicht erforderlich ist (z. B. benötigt Scala es nicht für Fallklassen) und dass es auch keine Mehrdeutigkeit gibt (da SieMyClass
in der KlasseMyClass
sowieso keine Methode haben können). Es gibt keine Mehrdeutigkeit fürString s = String("hello")
; es kann nichts anderes als ein Konstruktor sein. Und schließlich bin ich anderer Meinung: Code-Konventionen dienen dazu, die Syntax zu verbessern und zu klären, worüber Sie streiten!new
Schlüsselwort, weil sonst die Syntax von Java anders gewesen wäre"? Ich bin sicher, Sie können die Schwäche dieses Arguments erkennen;) Und ja, Sie diskutieren weiterhin die Syntax, nicht die Semantik. Auch Abwärtskompatibilität mit was? Wenn Sie eine neue Sprache wie Java entwerfen, sind Sie bereits inkompatibel mit C und C ++!In C # new ist es wichtig, zwischen auf dem Stapel erstellten Objekten und dem Heap zu unterscheiden. Häufig erstellen wir Objekte auf dem Stapel, um die Leistung zu verbessern. Sehen Sie, wenn ein Objekt auf dem Stapel den Gültigkeitsbereich verlässt, verschwindet es sofort, wenn sich der Stapel auflöst, genau wie ein Grundelement. Es ist nicht erforderlich, dass der Garbage Collector den Überblick behält, und es gibt keinen zusätzlichen Aufwand für den Speichermanager, um den erforderlichen Speicherplatz auf dem Heap zuzuweisen.
quelle