Cómo ocultar una propiedad heredada en una clase sin modificar la clase heredada (clase base)?

StackOverflow https://stackoverflow.com/questions/1875401

Pregunta

Si tengo el ejemplo de código siguiente:

public class ClassBase
{
    public int ID { get; set; }

    public string Name { get; set; }
}

public class ClassA : ClassBase
{
    public int JustNumber { get; set; }

    public ClassA()
    {
        this.ID = 0;
        this.Name = string.Empty;
        this.JustNumber = string.Empty;
    }
}

¿Qué debo hacer para ocultar la propiedad Name (No se muestra como un miembro de los miembros de ClassA) sin modificar ClassBase?

¿Fue útil?

Solución

huelo un olor código aquí. Es mi opinión que sólo se debe heredar una clase base si va a implementar toda la funcionalidad de la clase base. Lo que está haciendo en realidad no se representan los principios orientados a objetos correctamente. Por lo tanto, si desea heredar de su base, usted debe estar implementando Nombre, de lo contrario tienes tu herencia al revés. Su clase A debe ser su clase base y la clase base actual debe heredar de A si eso es lo que quiere, no al revés.

Sin embargo, no alejarse demasiado de la pregunta directa. Si hicieron quieren burlar "las reglas" y desea continuar en el camino que ha elegido - aquí es cómo puede ir sobre ella:

La convención es poner en práctica la propiedad, pero lanzar una NotImplementedException cuando esa propiedad se llama - si bien, no me gusta que sea. Pero esa es mi opinión personal y que no cambia el hecho de que esta convención sigue en pie.

Si usted está tratando de obsoleta la propiedad (y es declarado en la clase base como virtual), entonces se podría utilizar el atributo obsoleto en él:

[Obsolete("This property has been deprecated and should no longer be used.", true)]
public override string Name 
{ 
    get 
    { 
        return base.Name; 
    }
    set
    {
        base.Name = value;
    }
}

( Editar Como Brian señaló en los comentarios, el segundo parámetro del atributo hará que un error de compilación si alguien hace referencia a la propiedad Name, por lo que no serán capaces de utilizar incluso aunque se ha implementado en la clase derivada.)

O como he mencionado el uso NotImplementedException:

public override string Name
{
    get
    {
        throw new NotImplementedException();
    }
    set
    {
        throw new NotImplementedException();
    }
}

Sin embargo, si la propiedad no es declarados como virtuales, a continuación, puede utilizar la nueva palabra clave para reemplazarlo:

public new string Name
{
    get
    {
        throw new NotImplementedException();
    }
    set
    {
        throw new NotImplementedException();
    }
}

Puede seguir utilizando el atributo obsoleto de la misma manera como si se anula el método, o se puede tirar la NotImplementedException, lo que usted elija. Probablemente me volvería a usar:

[Obsolete("Don't use this", true)]
public override string Name { get; set; }

o

[Obsolete("Don't use this", true)]
public new string Name { get; set; }

En función de si o no se hubiera declarado como virtual en la clase base.

Otros consejos

Aunque técnicamente la propiedad no se oculta, una forma de desalentar fuertemente su uso es poner atributos en él como los siguientes:

[Browsable(false)]
[Bindable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]

Esto es lo que hace System.Windows.Forms para los controles que tienen propiedades que no encajan. La texto propiedad, por ejemplo, está en control, pero no tiene sentido en cada clase que hereda de control. Así que en MonthCalendar , por ejemplo, la propiedad de texto aparece como esto (por la fuente de referencia en línea):

[Browsable(false),
    EditorBrowsable(EditorBrowsableState.Never),
    Bindable(false), 
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text {
    get { return base.Text; }
    set { base.Text = value; }
}
  • navegable - si el miembro aparece en la ventana Propiedades
  • EditorBrowsable - si el miembro se muestra en el menú desplegable Intellisense

EditorBrowsable (falso) no le impide escribir la propiedad, y si se utiliza la propiedad, el proyecto aún se compilará. Pero ya que la propiedad no aparece en IntelliSense, no va a ser tan obvio que se puede usar.

Sólo ocultarlo

 public class ClassBase
{
    public int ID { get; set; }
    public string Name { get; set; }
}
public class ClassA : ClassBase
{
    public int JustNumber { get; set; }
    private new string Name { get { return base.Name; } set { base.Name = value; } }
    public ClassA()
    {
        this.ID = 0;
        this.Name = string.Empty;
        this.JustNumber = 0;
    }
}

Nota: Nombre seguirá siendo un miembro del público de ClassBase, dada la limitación de no cambiar la clase base no hay manera de detener ese

.

¿Por qué la herencia vigor cuando no es necesario? Creo que la forma correcta de hacerlo es haciendo tiene un- en lugar de un is-a .

public class ClassBase
{
    public int ID { get; set; }

    public string Name { get; set; }
}

public class ClassA
{
    private ClassBase _base;

    public int ID { get { return this._base.ID; } }

    public string JustNumber { get; set; }

    public ClassA()
    {
        this._base = new ClassBase();
        this._base.ID = 0;
        this._base.Name = string.Empty;
        this.JustNumber = string.Empty;
    }
}

I completamente de acuerdo que las propiedades no deben ser retirados de las clases de base, pero a veces una clase derivada podrían tener una forma diferente más apropiado para introducir los valores. En mi caso, por ejemplo, estoy heredando de ItemsControl. Como todos sabemos, ItemsControl tiene la propiedad ItemsSource, pero yo quiero que mi control para combinar datos de 2 fuentes (por ejemplo, persona y ubicación). Si yo fuera a tener el usuario introduzca los datos utilizando ItemsSource, necesitaría para separar y recombinar los valores, así que creé 2 propiedades para introducir los datos. Pero volviendo a la pregunta original, esto deja al ItemsSource, que no quiero que el usuario utilice porque estoy "reemplazando" con mis propias propiedades. Me gustan las ideas navegables y EditorBrowsable, pero todavía no impide que el usuario lo usen. El punto básico aquí es que la herencia debe mantener la mayor parte de las propiedades, pero cuando hay una clase compleja grande (especialmente en los que no se puede modificar el código original), reescribiendo todo sería muy ineficiente.

No creo que muchas de las personas que respondieron a entender aquí la herencia en absoluto. Hay una necesidad de heredar de una clase base y ocultar y funciones de su var vez pública. Ejemplo, digamos que usted tiene un motor básico y desea realizar un nuevo motor que está sobrealimentado. Así, el 99% del motor que va a utilizar, pero le retocar un poco de su funcionalidad para que funcione mucho mejor y sin embargo, todavía hay algunas funciones que sólo se debe mostrar a las modificaciones realizadas, no el usuario final. Porque todos sabemos que cada clase MS pone a cabo en realidad no necesitar ninguna modificación.

Además de utilizar el nuevo simplemente reemplazar la funcionalidad que es una de las cosas que Microsoft en sus infinitas WIS ... .. oh, me refiero a errores considerados una herramienta no vale la pena más.

La mejor manera de lograr esto es ahora la herencia de varios niveles.

public class classA 
{
}

public class B : A 
{} 

public class C : B 
{} 

Clase B hace todo su trabajo y la clase C expone lo que necesita expuesto.

No se puede, que es el punto de la herencia: la subclase debe ofrecer todos los métodos y propiedades de la clase base

.

Se puede cambiar la aplicación de una excepción cuando la propiedad se llama (si fuera virtual) ...

Creo que es un mal diseño si usted tiene que hacer esto, especialmente si usted es capaz de diseñar el código desde cero.

¿Por qué?

El buen diseño es dejar que las propiedades comunes de Acciones de la clase base que tiene un cierto concepto (virtuales o reales). Ejemplo:. System.IO.Stream en C #

Más abajo en el carril de mal diseño aumentará el costo de mantenimiento y realizar la aplicación cada vez más difícil. Evitar esto tanto como sea posible!

Las reglas básicas que utilizo:

  • Minimizar el número de propiedades y métodos de la clase base. Si no se vaya a utilizar algunas propiedades o métodos de una clase que hereda de la clase base; no lo ponga en los baseclass continuación. Si usted está en el developmentstage de un proyecto; Siempre volver al tablero de dibujo ahora una continuación para comprobar el diseño porque las cosas cambian! Rediseñar cuando sea necesario. Cuando el proyecto es vivir los costes para el cambio de las cosas más adelante en el diseño va a subir!

    • Si está utilizando una clase base implementado por un 3: rd partido, considere "subir" un nivel en lugar de "anular" con "NotImplementedException" o algo así. Si no hay otro nivel, considere diseñar el código desde cero.

    • Siempre se debe considerar para sellar las clases que no desea que nadie sea capaz de heredarlo. Obliga a los codificadores "subir un nivel" en la "jerarquía heredad," y por lo tanto "cabos sueltos" como "NotImplementedException" puede ser evitado.

Sé que la pregunta es viejo, pero lo que puede hacer es anular las PostFilterProperties como esto:

 protected override void PostFilterProperties(System.Collections.IDictionary properties)
    {
        properties.Remove("AccessibleDescription");
        properties.Remove("AccessibleName");
        properties.Remove("AccessibleRole");
        properties.Remove("BackgroundImage");
        properties.Remove("BackgroundImageLayout");
        properties.Remove("BorderStyle");
        properties.Remove("Cursor");
        properties.Remove("RightToLeft");
        properties.Remove("UseWaitCursor");
        properties.Remove("AllowDrop");
        properties.Remove("AutoValidate");
        properties.Remove("ContextMenuStrip");
        properties.Remove("Enabled");
        properties.Remove("ImeMode");
        //properties.Remove("TabIndex"); // Don't remove this one or the designer will break
        properties.Remove("TabStop");
        //properties.Remove("Visible");
        properties.Remove("ApplicationSettings");
        properties.Remove("DataBindings");
        properties.Remove("Tag");
        properties.Remove("GenerateMember");
        properties.Remove("Locked");
        //properties.Remove("Modifiers");
        properties.Remove("CausesValidation");
        properties.Remove("Anchor");
        properties.Remove("AutoSize");
        properties.Remove("AutoSizeMode");
        //properties.Remove("Location");
        properties.Remove("Dock");
        properties.Remove("Margin");
        properties.Remove("MaximumSize");
        properties.Remove("MinimumSize");
        properties.Remove("Padding");
        //properties.Remove("Size");
        properties.Remove("DockPadding");
        properties.Remove("AutoScrollMargin");
        properties.Remove("AutoScrollMinSize");
        properties.Remove("AutoScroll");
        properties.Remove("ForeColor");
        //properties.Remove("BackColor");
        properties.Remove("Text");
        //properties.Remove("Font");
    }

Puede utilizar Browsable(false)

[Browsable( false )]
public override string Name
{
    get { return base.Name; }
    set { base.Name= value; }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top