c# - que - Diferencia entre el objeto a=perro nuevo() vs perro a=perro nuevo()
peleas de perros y gatos juegos (6)
Ambas declaraciones implican llamar al constructor predeterminado de Dog
como usted mismo menciona; por lo tanto, es evidente que en ambos casos se construye una instancia Dog
. Esto significa que ambas declaraciones terminan inicializando una variable con una instancia idéntica (esta es la parte de la declaración después de los iguales).
Sin embargo, las declaraciones también tienen otra parte: la declaración de una variable (esta es la parte de la declaración antes de los iguales). En los lenguajes de tipo estático, como C #, cada variable, más generalmente, cualquier expresión, tiene un tipo estático:
object a = new Dog(); // static type: object / runtime type: Dog
Dog b = new Dog(); // static type: Dog / runtime type: Dog
El compilador no le permitirá asignar un valor a una variable que no puede probar es del tipo estático de la variable, por ejemplo, no permitiría
Cat c = new Dog(); // unless Dog derives from Cat, which we know isn''t true
Dado que todos los tipos de referencia derivan implícitamente de System.Object
, la asignación de un Dog
a una variable de object
tipo estático es OK. Puedes pensar en "tipo estático" como lo que el objeto es "declarado como". Siempre puede determinar el tipo estático de algo simplemente leyendo el código fuente ; así es como lo hace el compilador.
Luego también está el tipo de tiempo de ejecución de cada variable (expresión), que mencioné anteriormente. Esto es lo mismo en ambos casos, porque después de todo en ambos casos hemos creado un Dog
. Puede pensar en "tipo de tiempo de ejecución" como lo que es realmente el objeto. El tipo de tiempo de ejecución de algo no puede determinarse simplemente leyendo la fuente; solo lo determina mientras el programa se está ejecutando, de ahí el nombre. En C #, esto se hace llamando a GetType
.
Debería ser obvio que el tipo de tiempo de ejecución es algo que no puede hacer sin¹; todo tiene que "ser" algo después de todo. ¿Pero por qué molestarse en inventar la noción de tipo estático?
Puede pensar en tipos estáticos como un contrato entre usted (el programador) y el compilador. Al declarar que el tipo estático de b
es Dog
, le dice al compilador que no tiene la intención de usar esa variable para almacenar nada más que un Dog
. El compilador, a cambio, promete no permitirle violar su propósito declarado y produce un error si intenta hacerlo. También le impide usar d
de ninguna manera que no sea compatible con todo tipo de Dog
.
Considerar:
class Dog {
public void Woof();
}
Dog d = new Dog();
d.Woof(); // OK
object o = new Dog();
o.Woof(); // COMPILER ERROR
La última línea causa un error del compilador porque viola el contrato de tipeo estático: usted le dijo al compilador que o
puede ser cualquier cosa derivada de System.Object
, pero no todas las cosas derivadas de eso tienen un método Woof
. Entonces, el compilador intenta protegerte diciendo "¿Qué estás haciendo allí? No puedo probar" que lo que sea que esté dentro puede hacerlo. ¿Qué pasaría si fuera un Cat
? ".
Notas:
¹ Esto no significa que todos los objetos mágicamente saben lo que "es" en todos los idiomas. En algunos casos (por ejemplo, en C ++), esta información se puede usar al crear un objeto, pero luego se "olvida" para permitirle al compilador más libertad para optimizar el código. Si esto sucede, el objeto todavía es algo, pero no puedes empujarlo y preguntarle "¿qué eres?".
² En realidad, en este ejemplo trivial puede demostrar eso. Pero no elegirá usar este conocimiento porque honrar el contrato del tipo estático es el punto completo.
object a = new Dog();
vs
Dog a = new Dog();
En ambos casos, a.GetType()
da Dog
. Ambos invocan el mismo constructor (con la misma jerarquía).
Entonces, ¿puedes decirme la diferencia entre estas dos afirmaciones?
Ambas sentencias contienen una declaración y una invocación de constructor. Las invocaciones del constructor son idénticas, por lo tanto obtienes un Dog
en ambos casos. Las declaraciones son diferentes: en el primer caso, declaras una variable de tipo object
, una superclase de Dog
; en el segundo caso, declaras una variable de tipo Dog
. La diferencia es que en el código posterior puede invocar métodos de Dog
sin un molde solo cuando declara la variable como Dog
; si lo declaras como object
, necesitarías un yeso.
Ambos crean un objeto Dog. Solo el segundo le permite invocar directamente los métodos de Perro o tratarlo como un perro, por ejemplo, si necesita pasar el objeto a un método como un parámetro de tipo Dog
(o algo en la jerarquía de Perros que es más específico que simplemente object
).
object obj = new Dog();
// can only see members declared on object
var type = obj.GetType(); // can do this
Console.WriteLine(obj.ToString()); // also this
obj.Bark(); // Error! Bark is not a member of System.Object
Dog dog = new Dog();
// can do all of the methods declared for Object
dog.Bark(); // can finally use the method defined for Dog
Esto es útil cuando quiere usar polimorfismo y puede usar el método abstracto que tiene implementación en Dog. Por lo tanto, de esta manera el objeto es Perro, aun así es Objeto. Entonces puede usar esta manera cuando quiera usar polimorfismo.
Su primera línea crea una variable de tipo object
.
El compilador no te dejará tratar eso como un Dog
.
new Dog()
es una expresión que crea una nueva instancia Dog
. Invoca al constructor sin parámetros de la clase Dog
.
a
es una variable: una celda de almacenamiento en la memoria que contiene una referencia a la instancia Dog
después de la asignación.
La diferencia es que una variable Dog
solo puede contener una referencia a una instancia Dog
(o una instancia de cualquier clase que se deriva de Dog
), mientras que una variable object
puede contener una referencia a una instancia object
(o una instancia de cualquier clase que deriva del object
- que hace la clase Dog
).
Cuando tiene una variable Dog
, puede invocar cualquier método definido por la clase Dog
(y sus clases base) en la instancia referenciada. Cuando tiene una variable de object
, solo puede invocar los métodos de la clase de object
en la instancia.