2010-01-08 32 views
8

Ok, esta es la pregunta ... ¿está obsoleta la nueva palabra clave?¿Los objetos nuevos están obsoletos?

Considere en C# (y java, creo) que hay reglas estrictas para los tipos. Las clases son tipos de referencia y solo se pueden crear en el montón. Los tipos de POD se crean en la pila; si desea asignarlos en el montón, debe colocarlos en un tipo de objeto. En C#, structs son la excepción, se pueden crear en la pila o en el montón.

Dadas estas reglas, ¿tiene sentido que aún tengamos que usar la nueva palabra clave? ¿No tendría sentido para el lenguaje utilizar la estrategia de asignación adecuada en función del tipo?

Por ejemplo, actualmente tenemos a escribir:

SomeClassType x = new SomeClassType(); 

en lugar de

SomeClassType x = SomeClassType(); 

o incluso sólo

SomeClassType x; 

El compilador, basado en que el tipo que se está creando es un tipo de referencia, adelante y asigne la memoria para x en el montón.

Esto se aplica a otros lenguajes como ruby, php, et al. C/C++ permite al programador un mayor control sobre dónde se crean los objetos, por lo que tiene buenas razones para requerir la nueva palabra clave.

¿Es new solo un remanente de los años 60 y nuestro patrimonio basado en C?

+0

¿Y esto no es wiki de la comunidad porque ...? –

+0

No lo sé. ¿Crees que debería ser? –

+1

Esta es una pregunta perfectamente válida. Y una buena tambien. Sin necesidad de CW. – bsneeze

Respuesta

18
SomeClassType x = SomeClassType(); 

en este caso SomeClassType() podría ser un método ubicada en otro lugar, ¿cómo el compilador saber si llamar a este método o crear una nueva clase.

SomeClassType x; 

Esto no es muy útil, la mayoría de las personas declaran sus variables de este tipo y, a veces pueblan ellos más tarde cuando lo necesitan. Por lo tanto, no sería útil crear una instancia en la memoria cada vez que declara una variable.

+0

Es cierto, pero ¿no podría abordar esto estableciéndolo en nulo? –

+2

@flyfish: no si desea que sea inmutable (es decir'final' en Java u otros equivalentes de idiomas), ya que entonces no podría asignarle nada más. –

+1

si establece nulo cómo construirá más tarde? –

5

Para empezar:

SomeClassType x; 

no se ha inicializado por lo que no hay memoria debe asignarse.

Aparte de eso, ¿cómo evitar problemas donde hay un método con el mismo nombre que la clase.

Digamos que escribir algo de código:

int World() { return 3; } 

int hello = World(); 

y todo es agradable y alegre.

Ahora se escribe una nueva clase más adelante:

class World 
{ 
    ... 
} 

repente su línea int hello = World() es ambigua.

+1

* De repente, su línea int hello = World() es ambigua. * No son los lenguajes dinámicos (como python) los que pueden manejar este escenario muy bien, un lenguaje compilado debería arrojar un error (al igual que cuando creas un método que ya está definido) – OscarRyz

+0

Dado el poder de la reflexión, no creo que sea un problema. C# puede determinar la diferencia entre un tipo y una instancia del tipo con el mismo nombre (¡aunque no sea bueno hacerlo!). Aunque sería fácil para el compilador generar un diagnóstico en este caso –

+0

@Stan, en mi ejemplo World() es simplemente una función que devuelve un int, por lo que es perfectamente válido. – tster

0

Si no tiene un constructor sin parámetros, esto podría ponerse feo.

Si tiene varios constructores, esto podría ponerse muy feo.

1

He estado programando con Java durante un número de años y nunca me ha importado si mi objeto está en el montón o en la pila. Desde esa perspectiva, me da igual escribir new o no escribirlo.

Supongo que esto sería más relevante para otros idiomas.

Lo único que me importa es que la clase tenga las operaciones correctas y mis objetos se creen correctamente.

Por cierto, yo uso (o intento) para utilizar la palabra clave new sólo en la fábrica merthod por lo que mi cliente se parece a esto de todos modos

SomeClasType x = SomeClasType.newInstance(); 

Ver: Effective Java Item:1

+1

Los objetos Java nunca están en la pila. – tster

+2

En realidad, la máquina virtual Hotspot puede asignar objetos en la pila como una optimización si, después del análisis de escape, determina que es local para un método. Hotspot es muy inteligente con estas cosas, aunque el programador nunca debería preocuparse. –

+1

@Joe M: Yeap, es por eso que tenemos que marcar como variables finales a las que queremos acceder desde las clases internas. Pero ese es el trabajo del compilador. – OscarRyz

16

Su tercer método no funcionará, ya que a veces queremos definir un objeto de un tipo y asignarlo a una variable de otro tipo. Por ejemplo:

Stream strm = new NetworkStream(); 

Quiero un tipo de flujo (tal vez de transmitir alguna parte), pero internamente Quiero un tipo NetworkStream.

También muchas veces que crear un nuevo objeto, mientras que llamar a un método:

myobj.Foo(new NetworkStream()); 

haciendo que de esta manera:

myobj.Foo(NetworkStream()); 

es muy confuso. ¿Estoy creando un objeto o llamando a un método cuando digo NetworkStream()?

+0

Buen punto. No estaba tratando de cubrir todos los casos de uso aquí. Solo una pregunta general. –

+0

¿cuál es el propósito de esto? simplemente haga 'NetworkStream strm = new NetworkStream();' – tster

+0

Sí, el Stream strm = new NetworkStream() es un mal ejemplo ... probablemente sea mejor: Stream [] streams = new Stream [2]; streams [0] = new NetworkStream(); streams [1] = new FileStream(); Lo siento por el formato de mierda, no puedo encontrar la forma de codificar el formato en este cuadro de comentarios. –

3

Por razones de rendimiento, esta podría ser una mala idea. Por ejemplo, si quiere que x sea una referencia para un objeto que ya ha sido creado, sería un desperdicio de memoria y tiempo de procesador crear un objeto nuevo y luego deshacerse de él.

6

Si pudiera simplemente escribir SomeClassType x; y hacer que se inicializara automáticamente, eso no permitiría a los constructores con ningún parámetro. No todos los SomeClassType tendrán un constructor sin parámetros; ¿Cómo sabría el compilador qué argumentos suministrar?

public class Repository 
{ 
    private IDbConnection connection; 

    public Repository(IDbConnection connection) 
    { 
     if (connection == null) 
     { 
      throw new ArgumentNullException("connection"); 
     } 
     this.connection = connection; 
    } 
} 

¿Cómo se instancia este objeto con sólo Repository rep;? Requiere un objeto dependiente para funcionar correctamente.

no hablar, es posible que desee escribir el código de este modo:

Dictionary<int, SomeClass> instances = GetInstancesFromSomewhere(); 
SomeClass instance; 
if (instances.TryGetValue(1, out instance)) 
{ 
    // Do something 
} 

¿de verdad lo quieren auto-inicialización para usted?

Si acaba de escribir SomeClassType x = SomeClassType(), entonces esto no hace distinción entre un constructor y un método en el alcance.

más general:

Creo que hay un malentendido fundamental de lo que la palabra clave es para new.El hecho de que los tipos de valores se asignen en la pila y los tipos de "referencia" se asignen en el montón es un detalle de implementación . La palabra clave new es parte de la especificación . Como programador, no le importa si está asignado en el montón o la pila (la mayoría de las veces), pero debe especificar cómo se inicializa el objeto.

Hay otros tipos válidos de inicializadores también, tales como:

int[] values = { 1, 2, 3, 4 }; 

Voilà, una inicialización sin new. En este caso, el compilador fue lo suficientemente inteligente como para resolverlo, ya que proporcionó una expresión literal que define el objeto completo.

Así que supongo que mi "respuesta" es, no se preocupe por dónde existe el objeto en cuanto a la memoria; utilice la palabra clave new como está previsto, como un inicializador de objetos para los objetos que requieren inicialización.

2

¿No tendría sentido para el idioma utilizar la estrategia de asignación adecuada basado en el tipo?

Eso es exactamente lo que hace el compilador de C#/runtime. La palabra clave new es solo la sintaxis para construir un objeto de cualquier forma que tenga sentido para ese objeto.

Eliminar la palabra clave new haría menos obvio que se está llamando a un constructor. Para un ejemplo similar, considere out parámetros:

myDictionary.TryGetValue(key, out val); 

El compilador ya se sabe que es un valout. Si no lo dice, se queja. Pero hace que el código sea más legible para que se establezca.

Al menos, esa es la justificación: en los IDEs modernos, estas cosas se podían encontrar y resaltar de otras formas además del texto insertado real.

¿Es nuevo solo un holdover de los años 60 y nuestro patrimonio basado en C?

Definitivamente no. C no tiene una palabra clave new.

Cuestiones relacionadas