La newpalabra clave en lenguajes como Java, Javascript y C # crea una nueva instancia de una clase.
Esta sintaxis parece haber sido heredada de C ++, donde newse usa específicamente para asignar una nueva instancia de una clase en el montón y devolver un puntero a la nueva instancia. En C ++, esta no es la única forma de construir un objeto. También puede construir un objeto en la pila, sin usar new, y de hecho, esta forma de construir objetos es mucho más común en C ++.
Entonces, viniendo de un fondo C ++, la newpalabra clave en lenguajes como Java, Javascript y C # me pareció natural y obvia. Entonces comencé a aprender Python, que no tiene la newpalabra clave. En Python, una instancia se construye simplemente llamando al constructor, como:
f = Foo()
Al principio, esto me pareció un poco extraño, hasta que se me ocurrió que no hay razón para que Python lo tenga new, porque todo es un objeto, por lo que no hay necesidad de desambiguar entre varias sintaxis de constructor.
Pero luego pensé: ¿de qué sirve realmente newJava? ¿Por qué deberíamos decir Object o = new Object();? ¿Por qué no solo Object o = Object();? En C ++ definitivamente hay una necesidad new, ya que necesitamos distinguir entre la asignación en el montón y la asignación en la pila, pero en Java todos los objetos se construyen en el montón, entonces, ¿por qué incluso tener la newpalabra clave? La misma pregunta podría hacerse para Javascript. En C #, con el que estoy mucho menos familiarizado, creo que newpuede tener algún propósito en términos de distinguir entre tipos de objetos y tipos de valores, pero no estoy seguro.
De todos modos, me parece que muchos lenguajes que vinieron después de C ++ simplemente "heredaron" la newpalabra clave, sin realmente necesitarla. Es casi como una palabra clave vestigial . No parece que lo necesitemos por ningún motivo y, sin embargo, está ahí.
Pregunta: ¿Estoy en lo correcto sobre esto? ¿O hay alguna razón convincente que newdeba estar en lenguajes administrados en memoria inspirados en C ++ como Java, Javascript y C # pero no Python?
fuente

newpalabra clave. ¡Por supuesto que quiero crear un nuevo compilador variable y estúpido! Un buen lenguaje sería en mi opinión, tienen una sintaxis comof = heap Foo(),f = auto Foo().fno escapa de la función, asigne espacio de pila.fcuando la función de cierre regresa.Respuestas:
Tus observaciones son correctas. C ++ es una bestia complicada, y la
newpalabra clave se usó para distinguir entre algo que necesitabadeletemás tarde y algo que sería reclamado automáticamente. En Java y C #, descartaron ladeletepalabra clave porque el recolector de basura se encargaría de usted.Entonces, el problema es por qué mantuvieron la
newpalabra clave Sin hablar con las personas que escribieron el idioma es un poco difícil de responder. Mis mejores conjeturas se enumeran a continuación:newpalabra clave crea un objeto en el montón. Entonces, ¿por qué cambiar el comportamiento esperado?Ruby está en algún lugar entre Python y Java / C # en su uso
new. Básicamente, crea una instancia de un objeto como este:No es una palabra clave, es un método estático para la clase. Lo que eso significa es que si desea un singleton, puede anular la implementación predeterminada de
new()devolver la misma instancia cada vez. No es necesariamente recomendado, pero es posible.fuente
allocmétodo (más o menos lo mismo que el de Rubynew) también es solo un método de clase.En resumen, tienes razón. La palabra clave new es superflua en lenguajes como Java y C #. Aquí hay algunas ideas de Bruce Eckel, que fue miembro del Comité Estándar de C ++ en la década de 1990 y luego publicó libros sobre Java: http://www.artima.com/weblogs/viewpost.jsp?thread=260578
fuente
varpalabra clave no es tan buena comoautoen C ++, pero espero que mejore.Hay dos razones por las que puedo pensar:
newdistingue entre un objeto y un primitivonewsintaxis es un poco más legible (IMO)El primero es trivial. No creo que sea más difícil distinguir los dos de cualquier manera. El segundo es un ejemplo del punto del OP, que
newes algo redundante.Sin embargo, podría haber conflictos de espacio de nombres; considerar:
Podrías, sin estirar demasiado la imaginación, terminar fácilmente con una llamada infinitamente recursiva. El compilador tendría que imponer un error "Nombre de la función igual que el objeto". Esto realmente no estaría de más, pero es mucho más simple de usar
new, lo que indica queGo to the object of the same name as this method and use the method that matches this signature.Java es un lenguaje muy simple de analizar, y sospecho que esto ayuda en esa área.fuente
Java, por su parte, todavía tiene la dicotomía de C ++: no bastante todo es un objeto. Java tiene tipos incorporados (por ejemplo,
charyint) que no tienen que asignarse dinámicamente.Sin embargo, eso no significa que
newsea realmente necesario en Java: el conjunto de tipos que no necesitan asignarse dinámicamente es fijo y conocido. Cuando define un objeto, el compilador podría saber (y, de hecho, sabe) si es un valor simplecharo un objeto que debe asignarse dinámicamente.Me abstendré (una vez más) de opinar sobre lo que esto significa sobre la calidad del diseño de Java (o la falta del mismo, según sea el caso).
fuente
new, por lo que esta no es realmente la razón.En JavaScript lo necesita porque el constructor parece una función normal, entonces, ¿cómo debería saber JS que desea crear un nuevo objeto si no fuera por la nueva palabra clave?
fuente
Curiosamente, VB lo necesita: la distinción entre
que declara una variable sin asignarla, el equivalente de
Foo f;en C #, yque declara la variable y asigna una nueva instancia de la clase, el equivalente de
var f = new Foo();en C #, es una distinción sustantiva. En pre.NET VB, incluso podría usarDim f As FoooDim f As New Foo, porque no había sobrecarga en los constructores.fuente
Dim f As Foo()declara una matriz deFoos. ¡Oh Alegría! :-)Dim Foo As New Barefectivamente haríaFoouna propiedad que construiría unBarsi se leyera while (es decirNothing). Este comportamiento no se limitó a suceder una vez; el establecimientoFoodeNothingy después de leer sería crear otro nuevoBar.Me gustan muchas respuestas y me gustaría agregar esto:
hace que la lectura del código sea más fácil
No es que esta situación suceda a menudo, pero considere que quería un método en el nombre de un verbo que compartiera el mismo nombre que un sustantivo. C # y otro lenguaje tienen naturalmente la palabra
objectreservada. Pero si no fuera así, seríaFoo = object()el resultado de la llamada al método del objeto o sería instanciar un nuevo objeto. Con suerte, dicho lenguaje sin lanewpalabra clave tiene protecciones contra esta situación, pero al tener el requisito de lanewpalabra clave antes de llamar a un constructor, permite la existencia de un método con el mismo nombre que un objeto.fuente
Hay muchas cosas vestigiales en muchos lenguajes de programación. A veces está ahí por diseño (C ++ fue diseñado para ser lo más compatible posible con C), a veces, está ahí. Para un ejemplo más atroz, considere hasta qué punto se
switchpropagó la declaración C rota .No sé Javascript y C # lo suficientemente bien como para decirlo, pero no veo ninguna razón
newen Java, excepto que C ++ lo tenía.fuente
x = new Y()en JavaScript no crea una instancia de laYclase, porque JavaScript no tiene clases. Pero se parece a Java, por lo que lleva lanewpalabra clave hacia adelante desde Java, que por supuesto la llevó hacia adelante desde C ++.En C #, permite tipos visibles en contextos en los que de otro modo un miembro podría ocultarlos. El le permite tener una propiedad con el mismo nombre que su tipo. Considera lo siguiente,
Tenga en cuenta que el uso de
newpermite que quede claro que eseAddresses elAddresstipo, no elAddressmiembro. Esto permite que un miembro tenga el mismo nombre que su tipo. Sin esto, deberá prefijar el nombre del tipo para evitar la colisión de nombres, comoCAddress. Esto fue muy intencional ya que a Anders nunca le gustó la notación húngara ni nada similar y quería que C # fuera utilizable sin ella. El hecho de que también fuera familiar era una doble bonificación.fuente
Curiosamente, con el advenimiento del reenvío perfecto, la no colocación
newtampoco es necesaria en C ++. Entonces, podría decirse que ya no es necesario en ninguno de los idiomas mencionados.fuente
std::shared_ptr<int> foo();tendrá que llamar denew intalguna manera.No estoy seguro de si los diseñadores de Java tenían esto en mente, pero cuando piensas en los objetos como registros recursivos , podrías imaginar que
Foo(123)no devuelve un objeto sino una función cuyo punto de fijación es el objeto que se está creando (es decir, la función que devolvería el objeto si se da como argumento el objeto que se está construyendo). Y el propósito denewes "atar el nudo" y devolver ese punto de fijación. En otras palabras,newharía que el "objeto a ser" sea consciente de elloself.Este tipo de enfoque podría ayudar a formalizar la herencia, por ejemplo: podría extender una función de objeto con otra función de objeto y finalmente proporcionarles algo común
selfmediante el uso denew:Aquí
&combina dos funciones de objeto.En este caso
newpodría definirse como:fuente
Para permitir 'nulo'.
Junto con la asignación basada en el montón, Java adoptó el uso de objetos nulos. No solo como un artefacto, sino como una característica. Cuando los objetos pueden tener un estado nulo, debe separar la declaración de la inicialización. De ahí la nueva palabra clave.
En C ++ una línea como
Llamaría instantáneamente al constructor predeterminado.
fuente
Person me = NiloPerson meser Nil por defecto y usarPerson me = Person()para no Nil? Mi punto es que no parece que Nil haya sido un factor en esta decisión ...Person meser nulo ePerson me()invocar al constructor predeterminado. Por lo tanto, siempre necesitará paréntesis para invocar cualquier cosa, y así deshacerse de una irregularidad de C ++.La razón por la cual Python no lo necesita es por su sistema de tipos. Fundamentalmente, cuando ve
foo = bar()en Python, no importa si sebar()trata de un método que se invoca, una clase que se instancia o un objeto de función; en Python, no hay una diferencia fundamental entre un functor y una función (porque los métodos son objetos); e incluso podría argumentar que una clase que se instancia es un caso especial de un functor. Por lo tanto, no hay razón para crear una diferencia artificial en lo que está sucediendo (especialmente porque la administración de memoria está extremadamente oculta en Python).En un lenguaje con un sistema de mecanografía diferente, o en el que los métodos y las clases no son objetos, existe la posibilidad de una diferencia conceptual más fuerte entre crear un objeto y llamar a una función o functor. Por lo tanto, incluso si el compilador / intérprete no necesita la
newpalabra clave, es comprensible que pueda mantenerse en lenguajes que no hayan roto todos los límites que tiene Python.fuente
En realidad, en Java hay una diferencia al usar cadenas:
es diferente de
Suponiendo que la cadena
"myString"nunca se haya usado antes, la primera instrucción crea un solo objeto String en el grupo de cadenas (un área especial del montón) mientras que la segunda instrucción crea dos objetos, uno en el área de montón normal para los objetos y otro en el grupo de cadenas . Es bastante obvio que la segunda afirmación es inútil en este escenario particular, pero el lenguaje lo permite.Esto significa que new asegura que el objeto se crea en esa área especial del montón, asignada para la creación de instancias de objeto normal, pero puede haber otras formas de instanciar objetos sin él; el anterior es un ejemplo, y queda espacio para la extensibilidad.
fuente
String myString = String("myString");?" (tenga en cuenta la ausencia de lanewpalabra clave)class MyClass { public MyClass() {} public MyClass MyClass() {return null;} public void doSomething { MyClass myClass = MyClass();}} //which is it, constructor or method?Stringva en contra de las convenciones de estilo Java, por lo que puede asumir que cualquier método que comience con mayúsculas es un constructor. Y segundo, si Java no nos limita, entonces Scala tiene "clases de casos" donde el constructor se ve exactamente como dije. ¿Entonces, dónde está el problema?newde lenguajes administrados . He demostrado quenewno es necesario en absoluto (por ejemplo, Scala no lo necesita para las clases de casos) y también que no hay ambigüedad (ya que de todos modos no puede tener un método nombradoMyClassen la claseMyClass). No hay ambigüedad paraString s = String("hello"); No puede ser otra cosa que un constructor. Y finalmente, no estoy de acuerdo: las convenciones de código están ahí para mejorar y aclarar la sintaxis, ¡de eso es lo que estás discutiendo!newpalabra clave porque de lo contrario la sintaxis de Java habría sido diferente"? Estoy seguro de que puedes ver la debilidad de ese argumento;) Y sí, sigues discutiendo la sintaxis, no la semántica. Además, ¿ compatibilidad hacia atrás con qué? Si está diseñando un nuevo lenguaje, como Java, ¡ya es incompatible con C y C ++!En C # new es importante distinguir entre los objetos creados en la pila y el montón. Con frecuencia creamos objetos en la pila para un mejor rendimiento. Vea, cuando un objeto en la pila se sale del alcance, desaparece inmediatamente cuando la pila se desenreda, como un primitivo. No es necesario que el recolector de basura realice un seguimiento, y no hay una sobrecarga adicional del administrador de memoria para asignar el espacio necesario en el montón.
fuente