2012-01-13 10 views
21

Quiero que esto me diga el Nombre de ambos ItemA y ItemB. Debería decirme "Subitem \ nSubitem", pero en su lugar me dice "Item \ nSubitem". Esto se debe a que la variable "Nombre" definida en la clase Subtema es técnicamente una variable diferente a la variable "Nombre" definida en la clase de Artículo base. Quiero cambiar la variable original a un nuevo valor. No entiendo por qué esto no es lo más fácil que haya existido, teniendo en cuenta que la virtualización y la anulación funcionan perfectamente con los métodos. He sido completamente incapaz de averiguar cómo realmente anular una variable.¿Cómo anulo, no oculto, una variable miembro (campo) en una subclase C#?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace Example 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      System.Console.WriteLine(ItemA.Name); 
      System.Console.WriteLine(ItemB.Name); 
      System.Console.ReadKey(); 
     } 
     static Item ItemA = new Subitem(); 
     static Subitem ItemB = new Subitem(); 
    } 
    public class Item 
    { 
     public string Name = "Item"; 
    } 
    public class Subitem : Item 
    { 
     new public string Name = "Subitem"; 
    } 
} 
+1

Necesita algo que pueda ser * virtual * - a * Propiedad * ("Getter") o un * Método *. Las variables de miembro son * nunca * virtuales. –

Respuesta

29

No se puede anulación variables en C#, pero se puede reemplazar propiedades:

public class Item 
{ 
    public virtual string Name {get; protected set;} 
} 
public class Subitem : Item 
{ 
    public override string Name {get; protected set;} 
} 

Otro enfoque sería cambiar el valor en la subclase, así:

public class Item 
{ 
    public string Name = "Item"; 
} 
public class Subitem : Item 
{ 
    public Subitem() 
    { 
     Name = "Subitem"; 
    } 
} 
+1

@ Eagle-Eye ¿Qué harían las variables polimórficas? No critiques la práctica si no puedes articular la teoría. –

+0

+1 a Jon, @ Eagle-Eye. Dado que el polimorfismo se trata de sustituir la * funcionalidad * en los tipos derivados, aplicarlo a campos similares (que no tienen ninguna funcionalidad) no tiene sentido. –

+0

@Jon Releyendo mi comentario ahora fue un poco estúpido de decir. Lo que realmente quise decir es que desearía poder establecer el valor predeterminado de una variable dentro de una clase hija sin tenerlo en el constructor (ya que provengo de un lenguaje de scripting donde fue así como se hizo). Hice un mal trabajo de expresar eso previamente. Sin embargo, ¿qué significa "no criticar la práctica si no puedes articular la teoría"? En cuanto a "los otros métodos parecen estúpidos y hacky", me refería a que hice un método de obtención simplemente para tener un valor predeterminado por separado. (Lamento el uso de la palabra estúpido, sin embargo.) –

8

No existe el concepto de polimorfismo (que es lo que hace que override haga su trabajo) con los campos (lo que se llama a una las variables). Lo que necesita usar aquí en cambio es una propiedad.

public class Item 
{ 
    public virtual string Name 
    { 
     get { return "Item"; } 
    } 
} 

public class SubItem : Item 
{ 
    public override string Name 
    { 
     get { return "Subitem"; } 
    } 
} 
+1

Aunque probablemente no haya codificado los valores de esa manera, puede variar. –

+0

Absolutamente correcto. Una "variable virtual" no tiene sentido. Lo cual es una gran parte de por qué los métodos "getter()" y "setter()" de Java son muy útiles.Y la noción de "propiedades" de C# (un avance de las "propiedades" ya muy buenas de Delphi) elimina gran parte de la necesidad de métodos getter/setter. "Propiedades" es definitivamente la respuesta a esta pregunta. Véase también este hilo: http://stackoverflow.com/questions/1112458/c-sharp-member-variable-overrides-used-by-base-class-method – paulsm4

+1

@JeffMercado: Aunque es cierto, estaba tratando de mantenerme tan cerca a la forma original de la pregunta del OP para demostrar la distinción de la que estoy hablando (propiedades vs. campos). –

0

Una posible solución sería usar una propiedad y anular su getter, como lo siguiente:

public class Item 
{ 
    public virtual string Name { get { return "Item"; } } 
} 
public class Subitem : Item 
{ 
    public override string Name { get { return "Subitem"; } } 
} 
+1

Esto evitaría cambiar el valor más adelante. – x3ro

4

¿Qué significa "invalidar una variable"?

Una variable es una ubicación con nombre en la memoria conceptual ("conceptual", porque podría ser un registro, aunque no muy probable con los campos).

Reemplazar un método sustituye un conjunto de operaciones por otro.

Dado que una ubicación con nombre en la memoria no es un conjunto de operaciones, ¿cómo se puede sustituir? ¿Qué cosas esperan usar esa ubicación nombrada en memoria que se supone que tiene que hacer?

Si desea cambiar lo que está almacenado en la memoria, a continuación, sólo lo hacen cuando la clase derivada se construye:

public class Item 
{ 
    public string Name = "Item"; 
} 
public class Subitem : Item 
{ 
    public SubItem() 
    { 
    Name = "Subitem"; 
    } 
} 

Si desea anular como conjunto de operaciones, a continuación, definir un conjunto de operaciones (un método o propiedad) para anular.

1

Esta pregunta es relativamente antigua y es probable que el autor haya utilizado C# 5.0 o una versión anterior. Pero tuve la misma pregunta y encontré una solución muy buena que funciona con C# 6.0 y superior que quiero compartir con usted:

C# 6.0 le da la capacidad de inicializar propiedades automáticas. Entonces uno puede usar solo eso:

public class Item 
{ 
    public virtual string Name { get; set; } = "Item"; 
} 

public class Subitem : Item 
{ 
    public override string Name { get; set; } = "Subitem"; 
} 
Cuestiones relacionadas