visual studio qué poo polimorfismo herencia ejemplo clases c# properties field

c# - studio - Anulación de campos o propiedades en subclases



visual studio c# herencia (8)

Tengo una clase base abstracta y quiero declarar un campo o una propiedad que tendrá un valor diferente en cada clase que hereda de esta clase principal.

Quiero definirlo en la clase base para poder hacer referencia a él en un método de clase base, por ejemplo anulando ToString para decir "Este objeto es de tipo propiedad / campo ". Tengo tres maneras de hacerlo, pero me preguntaba: ¿cuál es la forma mejor o más aceptada de hacer esto? Pregunta de novato, lo siento

Opción 1:
Usa una propiedad abstracta y anótala en las clases heredadas. Esto se ve reforzado (tiene que anularlo) y está limpio. Sin embargo, se siente un poco mal devolver un valor de código duro en lugar de encapsular un campo y se trata de unas pocas líneas de código en lugar de solo. También tengo que declarar un cuerpo para "establecer", pero eso es menos importante (y probablemente haya una forma de evitar aquello de lo que no tengo conocimiento).

abstract class Father { abstract public int MyInt { get; set;} } class Son : Father { public override int MyInt { get { return 1; } set { } } }

opcion 2
Puedo declarar un campo público (o un campo protegido) y anularlo explícitamente en la clase heredada. El siguiente ejemplo me dará una advertencia para usar "nuevo" y probablemente pueda hacer eso, pero se siente mal y rompe el polimorfismo, que fue el punto. No parece una buena idea ...

abstract class Mother { public int MyInt = 0; } class Daughter : Mother { public int MyInt = 1; }

Opción 3
Puedo usar un campo protegido y establecer el valor en el constructor. Esto parece bastante ordenado, pero confío en que me asegure de que el constructor siempre establezca esto y con múltiples constructores sobrecargados siempre hay una posibilidad de que alguna ruta de código no establezca el valor.

abstract class Aunt { protected int MyInt; } class Niece : Aunt { public Niece() { MyInt = 1; } }

Es un poco una pregunta teórica y creo que la respuesta debe ser la opción 1, ya que es la única opción segura , pero estoy empezando a entender C # y quería preguntar esto a las personas con más experiencia.


De las tres soluciones, solo la Opción 1 es polimórfica .

Los campos en sí mismos no pueden ser anulados. Que es exactamente por qué la Opción 2 devuelve la nueva advertencia de palabra clave.

La solución a la advertencia no es agregar la palabra clave "nueva", sino implementar la Opción 1.

Si necesita que su campo sea polimórfico, debe envolverlo en una propiedad.

La opción 3 está bien si no necesitas comportamiento polimórfico. Sin embargo, debe recordar que cuando en el tiempo de ejecución se accede a la propiedad MyInt, la clase derivada no tiene control sobre el valor devuelto. La clase base en sí misma es capaz de devolver este valor.

Así es como podría verse una implementación verdaderamente polimórfica de su propiedad, permitiendo que las clases derivadas tengan el control .

abstract class Parent { abstract public int MyInt { get; } } class Father : Parent { public override int MyInt { get { /* Apply formula "X" and return a value */ } } } class Mother : Parent { public override int MyInt { get { /* Apply formula "Y" and return a value */ } } }


Hice esto...

namespace Core.Text.Menus { public abstract class AbstractBaseClass { public string SELECT_MODEL; public string BROWSE_RECORDS; public string SETUP; } } namespace Core.Text.Menus { public class English : AbstractBaseClass { public English() { base.SELECT_MODEL = "Select Model"; base.BROWSE_RECORDS = "Browse Measurements"; base.SETUP = "Setup Instrument"; } } }

De esta manera todavía puede usar campos.


La opción 2 no es inicial, no puede anular los campos, solo puede ocultarlos .

Personalmente, iría por la opción 1 todo el tiempo. Intento mantener los campos privados en todo momento. Eso es si realmente necesita poder anular la propiedad, por supuesto. Otra opción es tener una propiedad de solo lectura en la clase base que se establece desde un parámetro de constructor:

abstract class Mother { private readonly myInt; public int MyInt { get { return myInt; } } protected Mother(int myInt) { this.myInt = myInt; } } class Daughter : Mother { public Daughter() : base(1) { } }

Ese es probablemente el enfoque más apropiado si el valor no cambia durante la vida de la instancia.


Me gustaría ir con la opción 3, pero tengo un método abstracto setMyInt que las subclases están obligadas a implementar. De esta forma, no tendrás el problema de que una clase derivada olvide establecerlo en el constructor.

abstract class Base { protected int myInt; protected abstract void setMyInt(); } class Derived : Base { override protected void setMyInt() { myInt = 3; } }

Por cierto, con la opción uno, si no especificas establecer; en su propiedad abstracta de clase base, la clase derivada no tendrá que implementarla.

abstract class Father { abstract public int MyInt { get; } } class Son : Father { public override int MyInt { get { return 1; } } }


Podrías definir algo como esto:

abstract class Father { //Do you need it public? protected readonly int MyInt; } class Son : Father { public Son() { MyInt = 1; } }

Al establecer el valor como de solo lectura, garantiza que el valor para esa clase permanezca sin cambios durante la vida del objeto.

Supongo que la siguiente pregunta es: ¿por qué la necesitas?


Podrías hacer esto

class x { private int _myInt; internal virtual int myInt { get { return _myInt; } set { _myInt = value; } } } class y : x { private int _myYInt; public override int myInt { get { return _myYInt; } set { _myYInt = value; } } }

virtual le permite obtener una propiedad, un cuerpo que hace algo y aún permite que las subclases lo anulen.


Puede ir con la opción 3 si modifica su clase base abstracta para requerir el valor de la propiedad en el constructor, no perderá ninguna ruta. Realmente consideraría esta opción.

abstract class Aunt { protected int MyInt; protected Aunt(int myInt) { MyInt = myInt; } }

Por supuesto, aún tiene la opción de hacer que el campo sea privado y luego, dependiendo de la necesidad, exponer un comprador de propiedad protegido o público.


la opción 2 es una mala idea. Dará lugar a algo llamado sombreado; Básicamente tiene dos miembros "MyInt" diferentes, uno en la madre y el otro en la hija. El problema con esto es que los métodos que se implementan en la madre harán referencia al "MyInt" de la madre, mientras que los métodos implementados en la hija harán referencia al "MyInt" de la hija. esto puede causar problemas graves de legibilidad y confusión más adelante.

Personalmente, creo que la mejor opción es 3; porque proporciona un valor centralizado claro, y los niños pueden referenciarlo internamente sin la molestia de definir sus propios campos, que es el problema con la opción 1.