La new
palabra clave en lenguajes como Java, Javascript y C # crea una nueva instancia de una clase.
Esta sintaxis parece haber sido heredada de C ++, donde new
se 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 new
palabra clave en lenguajes como Java, Javascript y C # me pareció natural y obvia. Entonces comencé a aprender Python, que no tiene la new
palabra 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 new
Java? ¿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 new
palabra clave? La misma pregunta podría hacerse para Javascript. En C #, con el que estoy mucho menos familiarizado, creo que new
puede 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 new
palabra 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 new
deba estar en lenguajes administrados en memoria inspirados en C ++ como Java, Javascript y C # pero no Python?
fuente
new
palabra 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()
.f
no escapa de la función, asigne espacio de pila.f
cuando la función de cierre regresa.Respuestas:
Tus observaciones son correctas. C ++ es una bestia complicada, y la
new
palabra clave se usó para distinguir entre algo que necesitabadelete
más tarde y algo que sería reclamado automáticamente. En Java y C #, descartaron ladelete
palabra clave porque el recolector de basura se encargaría de usted.Entonces, el problema es por qué mantuvieron la
new
palabra 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:new
palabra 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
alloc
mé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
var
palabra clave no es tan buena comoauto
en C ++, pero espero que mejore.Hay dos razones por las que puedo pensar:
new
distingue entre un objeto y un primitivonew
sintaxis 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
new
es 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,
char
yint
) que no tienen que asignarse dinámicamente.Sin embargo, eso no significa que
new
sea 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 simplechar
o 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 Foo
oDim f As New Foo
, porque no había sobrecarga en los constructores.fuente
Dim f As Foo()
declara una matriz deFoo
s. ¡Oh Alegría! :-)Dim Foo As New Bar
efectivamente haríaFoo
una propiedad que construiría unBar
si se leyera while (es decirNothing
). Este comportamiento no se limitó a suceder una vez; el establecimientoFoo
deNothing
y 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
object
reservada. 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 lanew
palabra clave tiene protecciones contra esta situación, pero al tener el requisito de lanew
palabra 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
switch
propagó la declaración C rota .No sé Javascript y C # lo suficientemente bien como para decirlo, pero no veo ninguna razón
new
en Java, excepto que C ++ lo tenía.fuente
x = new Y()
en JavaScript no crea una instancia de laY
clase, porque JavaScript no tiene clases. Pero se parece a Java, por lo que lleva lanew
palabra 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
new
permite que quede claro que eseAddress
es elAddress
tipo, no elAddress
miembro. 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
new
tampoco 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 int
alguna 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 denew
es "atar el nudo" y devolver ese punto de fijación. En otras palabras,new
harí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
self
mediante el uso denew
:Aquí
&
combina dos funciones de objeto.En este caso
new
podrí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 = Nil
oPerson me
ser 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 me
ser 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
new
palabra 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 lanew
palabra clave)class MyClass { public MyClass() {} public MyClass MyClass() {return null;} public void doSomething { MyClass myClass = MyClass();}} //which is it, constructor or method?
String
va 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?new
de lenguajes administrados . He demostrado quenew
no 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 nombradoMyClass
en 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!new
palabra 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