Compartir a través de


Control de versiones con las palabras clave Override y New (Guía de programación de C#)

El lenguaje C# está diseñado para que el control de versiones entre las clases base y derivadas de diferentes bibliotecas pueda evolucionar y mantener la compatibilidad con versiones anteriores. Esto significa, por ejemplo, que la introducción de un nuevo miembro en una clase base con el mismo nombre que un miembro de una clase derivada es totalmente compatible con C# y no conduce a un comportamiento inesperado. También significa que una clase debe indicar explícitamente si un método está diseñado para invalidar un método heredado o si un método es un nuevo método que oculta un método heredado con nombre similar.

En C#, las clases derivadas pueden contener métodos con el mismo nombre que los métodos de clase base.

  • Si el método de la clase derivada no está precedido de palabras clave nuevas o invalidadas , el compilador emitirá una advertencia y el método se comportará como si la new palabra clave estuviera presente.

  • Si el método de la clase derivada está precedido de la new palabra clave , el método se define como independiente del método de la clase base.

  • Si el método de la clase derivada está precedido de la override palabra clave , los objetos de la clase derivada llamarán a ese método en lugar del método de clase base.

  • Para aplicar la override palabra clave al método de la clase derivada, el método de clase base debe definirse virtual.

  • Se puede llamar al método de clase base desde dentro de la clase derivada mediante la base palabra clave .

  • Las overridepalabras clave , virtualy new también se pueden aplicar a propiedades, indexadores y eventos.

De forma predeterminada, los métodos de C# no son virtuales. Si un método se declara como virtual, cualquier clase que herede el método puede implementar su propia versión. Para que un método sea virtual, el virtual modificador se usa en la declaración de método de la clase base. A continuación, la clase derivada puede invalidar el método virtual base mediante la override palabra clave u ocultar el método virtual en la clase base mediante la new palabra clave . Si no se especifica la override palabra clave ni la new palabra clave , el compilador emitirá una advertencia y el método de la clase derivada ocultará el método en la clase base.

Para demostrar esto en la práctica, supongamos por un momento que la Empresa A ha creado una clase denominada GraphicsClass, que usa el programa. La siguiente es GraphicsClass:

class GraphicsClass
{
    public virtual void DrawLine() { }
    public virtual void DrawPoint() { }
}

Su empresa usa esta clase y la usa para derivar su propia clase, agregando un nuevo método:

class YourDerivedGraphicsClass : GraphicsClass
{
    public void DrawRectangle() { }
}

La aplicación se usa sin problemas, hasta que la empresa A publica una nueva versión de GraphicsClass, que se parece al código siguiente:

class GraphicsClass
{
    public virtual void DrawLine() { }
    public virtual void DrawPoint() { }
    public virtual void DrawRectangle() { }
}

La nueva versión de GraphicsClass ahora contiene un método denominado DrawRectangle. Inicialmente, no ocurre nada. La nueva versión sigue siendo binaria compatible con la versión anterior. Cualquier software que haya implementado seguirá funcionando, incluso si la nueva clase está instalada en esos sistemas informáticos. Las llamadas existentes al método DrawRectangle seguirán haciendo referencia a tu versión en la clase derivada.

Sin embargo, en cuanto vuelva a compilar la aplicación mediante la nueva versión de GraphicsClass, recibirá una advertencia del compilador, CS0108. Esta advertencia le informa que debe considerar cómo desea que su método DrawRectangle se comporte en su aplicación.

Si desea que el método invalide el nuevo método de clase base, use la override palabra clave :

class YourDerivedGraphicsClass : GraphicsClass
{
    public override void DrawRectangle() { }
}

La override palabra clave garantiza que los objetos derivados de YourDerivedGraphicsClass usarán la versión de clase derivada de DrawRectangle. Los objetos derivados de YourDerivedGraphicsClass todavía pueden tener acceso a la versión de clase base de DrawRectangle mediante la palabra clave base:

base.DrawRectangle();

Si no desea que el método invalide el nuevo método de clase base, se aplican las siguientes consideraciones. Para evitar confusiones entre los dos métodos, puede cambiar el nombre del método. Esto puede ser lento y propenso a errores, y simplemente no práctico en algunos casos. Sin embargo, si el proyecto es relativamente pequeño, puede usar las opciones de refactorización de Visual Studio para cambiar el nombre del método. Para obtener más información, vea Refactorización de clases y tipos (Diseñador de clases).

Como alternativa, puede evitar la advertencia mediante la palabra clave new en la definición de clase derivada:

class YourDerivedGraphicsClass : GraphicsClass
{
    public new void DrawRectangle() { }
}

El uso de la new palabra clave indica al compilador que la definición oculta la definición contenida en la clase base. Este es el comportamiento predeterminado.

Selección de método y reemplazo

Cuando se llama a un método en una clase, el compilador de C# selecciona el mejor método para llamar si más de un método es compatible con la llamada, como cuando hay dos métodos con el mismo nombre y parámetros que son compatibles con el parámetro pasado. Los métodos siguientes serían compatibles:

public class Derived : Base
{
    public override void DoWork(int param) { }
    public void DoWork(double param) { }
}

Cuando DoWork se llama a en una instancia de Derived, el compilador de C# intentará primero hacer que la llamada sea compatible con las versiones de DoWork declaradas originalmente en Derived. Los métodos de invalidación no se consideran declarados en una clase, son nuevas implementaciones de un método declarado en una clase base. Solo si el compilador de C# no puede coincidir con la llamada de método a un método original en Derived, intentará hacer coincidir la llamada a un método invalidado con el mismo nombre y parámetros compatibles. Por ejemplo:

int val = 5;
Derived d = new();
d.DoWork(val);  // Calls DoWork(double).

Dado que la variable val se puede convertir a un doble implícitamente, el compilador de C# llama a DoWork(double) en lugar de DoWork(int). Hay dos maneras de evitar esto. En primer lugar, evite declarar nuevos métodos con el mismo nombre que los métodos virtuales. En segundo lugar, puede indicar al compilador de C# que llame al método virtual haciendo que busque en la lista de métodos de clase base mediante la conversión de la instancia de Derived en Base. Como el método es virtual, se llamará a la implementación de DoWork(int) en Derived. Por ejemplo:

((Base)d).DoWork(val);  // Calls DoWork(int) on Derived.

Para obtener otros ejemplos de new y override, vea Saber cuándo utilizar las palabras clave Override y New (Guía de programación de C#).

Consulte también