Saber cuándo utilizar las palabras clave Override y New (Guía de programación de C#)Knowing When to Use Override and New Keywords (C# Programming Guide)

En C#, un método de una clase derivada puede tener el mismo nombre que un método de la clase base.In C#, a method in a derived class can have the same name as a method in the base class. Se puede especificar cómo interactúan los métodos mediante las palabras clave new y override.You can specify how the methods interact by using the new and override keywords. El modificador override extiende el método de clase base virtual y el modificador new oculta un método de clase base accesible.The override modifier extends the base class virtual method, and the new modifier hides an accessible base class method. En los ejemplos de este tema se ilustra la diferencia.The difference is illustrated in the examples in this topic.

En una aplicación de consola, declare las dos clases siguientes, BaseClass y DerivedClass.In a console application, declare the following two classes, BaseClass and DerivedClass. DerivedClass hereda de BaseClass.DerivedClass inherits from BaseClass.

class BaseClass  
{  
    public void Method1()  
    {  
        Console.WriteLine("Base - Method1");  
    }  
}  
  
class DerivedClass : BaseClass  
{  
    public void Method2()  
    {  
        Console.WriteLine("Derived - Method2");  
    }  
}  

En el método Main, declare las variables bc, dc y bcdc.In the Main method, declare variables bc, dc, and bcdc.

  • bc es de tipo BaseClass, y su valor es de tipo BaseClass.bc is of type BaseClass, and its value is of type BaseClass.

  • dc es de tipo DerivedClass, y su valor es de tipo DerivedClass.dc is of type DerivedClass, and its value is of type DerivedClass.

  • bcdc es de tipo BaseClass, y su valor es de tipo DerivedClass.bcdc is of type BaseClass, and its value is of type DerivedClass. Esta es la variable a la que hay que prestar atención.This is the variable to pay attention to.

Dado que bc y bcdc tienen el tipo BaseClass, solo pueden tener acceso directo a Method1, a menos que se use la conversión.Because bc and bcdc have type BaseClass, they can only directly access Method1, unless you use casting. La variable dc puede tener acceso a Method1 y Method2.Variable dc can access both Method1 and Method2. Estas relaciones se muestran en el código siguiente.These relationships are shown in the following code.

class Program  
{  
    static void Main(string[] args)  
    {  
        BaseClass bc = new BaseClass();  
        DerivedClass dc = new DerivedClass();  
        BaseClass bcdc = new DerivedClass();  
  
        bc.Method1();  
        dc.Method1();  
        dc.Method2();  
        bcdc.Method1();  
    }  
    // Output:  
    // Base - Method1  
    // Base - Method1  
    // Derived - Method2  
    // Base - Method1  
}  

Después, agregue el método Method2 siguiente a BaseClass.Next, add the following Method2 method to BaseClass. La firma de este método coincide con la firma del método Method2 de DerivedClass.The signature of this method matches the signature of the Method2 method in DerivedClass.

public void Method2()  
{  
    Console.WriteLine("Base - Method2");  
}  

Dado que BaseClass ahora tiene un método Method2, se puede agregar una segunda instrucción de llamada para las variables de BaseClass bc y bcdc, como se muestra en el código siguiente.Because BaseClass now has a Method2 method, a second calling statement can be added for BaseClass variables bc and bcdc, as shown in the following code.

bc.Method1();  
bc.Method2();  
dc.Method1();  
dc.Method2();  
bcdc.Method1();  
bcdc.Method2();  

Al compilar el proyecto, verá que la adición del método Method2 de BaseClass genera una advertencia.When you build the project, you see that the addition of the Method2 method in BaseClass causes a warning. La advertencia indica que el método Method2 de DerivedClass oculta el método Method2 de BaseClass.The warning says that the Method2 method in DerivedClass hides the Method2 method in BaseClass. Se recomienda usar la palabra clave new en la definición de Method2 si se pretende provocar ese resultado.You are advised to use the new keyword in the Method2 definition if you intend to cause that result. Como alternativa, se puede cambiar el nombre de uno de los métodos Method2 para resolver la advertencia, pero eso no siempre resulta práctico.Alternatively, you could rename one of the Method2 methods to resolve the warning, but that is not always practical.

Antes de agregar new, ejecute el programa para ver el resultado producido por las instrucciones adicionales que realizan la llamada.Before adding new, run the program to see the output produced by the additional calling statements. Se muestran los resultados siguientes.The following results are displayed.

// Output:  
// Base - Method1  
// Base - Method2  
// Base - Method1  
// Derived - Method2  
// Base - Method1  
// Base - Method2  

La palabra clave new conserva las relaciones que generan ese resultado, pero se suprime la advertencia.The new keyword preserves the relationships that produce that output, but it suppresses the warning. Las variables de tipo BaseClass siguen teniendo acceso a los miembros de BaseClass y la variable de tipo DerivedClass sigue teniendo acceso a los miembros de DerivedClass en primer lugar y, después, tiene en cuenta los miembros heredados de BaseClass.The variables that have type BaseClass continue to access the members of BaseClass, and the variable that has type DerivedClass continues to access members in DerivedClass first, and then to consider members inherited from BaseClass.

Para suprimir la advertencia, agregue el modificador new a la definición de Method2 en DerivedClass, como se muestra en el código siguiente.To suppress the warning, add the new modifier to the definition of Method2 in DerivedClass, as shown in the following code. Se puede agregar el modificador antes o después de public.The modifier can be added before or after public.

public new void Method2()  
{  
    Console.WriteLine("Derived - Method2");  
}  

Vuelva a ejecutar el programa para comprobar que el resultado no ha cambiado.Run the program again to verify that the output has not changed. Compruebe también que ya no aparece la advertencia.Also verify that the warning no longer appears. Mediante el uso de new, afirma que es consciente de que el miembro que modifica oculta un miembro heredado de la clase base.By using new, you are asserting that you are aware that the member that it modifies hides a member that is inherited from the base class. Para más información sobre la ocultación de nombres a través de la herencia, vea new (Modificador, Referencia de C#).For more information about name hiding through inheritance, see new Modifier.

Para contrastar este comportamiento con los efectos de usar override, agregue el método siguiente a DerivedClass.To contrast this behavior to the effects of using override, add the following method to DerivedClass. Se puede agregar el modificador override antes o después de public.The override modifier can be added before or after public.

public override void Method1()  
{  
    Console.WriteLine("Derived - Method1");  
}  

Agregue el modificador virtual a la definición de Method1 en BaseClass.Add the virtual modifier to the definition of Method1 in BaseClass. Se puede agregar el modificador virtual antes o después de public.The virtual modifier can be added before or after public.

public virtual void Method1()  
{  
    Console.WriteLine("Base - Method1");  
}  

Vuelva a ejecutar el proyecto.Run the project again. Observe especialmente las dos últimas líneas del resultado siguiente.Notice especially the last two lines of the following output.

// Output:  
// Base - Method1  
// Base - Method2  
// Derived - Method1  
// Derived - Method2  
// Derived - Method1  
// Base - Method2  

El uso del modificador override permite que bcdc tenga acceso al método Method1 que se define en DerivedClass.The use of the override modifier enables bcdc to access the Method1 method that is defined in DerivedClass. Normalmente, es el comportamiento deseado en jerarquías de herencia.Typically, that is the desired behavior in inheritance hierarchies. La intención es que los objetos que tienen valores que se crean a partir de la clase derivada usen los métodos que se definen en la clase derivada.You want objects that have values that are created from the derived class to use the methods that are defined in the derived class. Ese comportamiento se consigue mediante el uso de override para extender el método de clase base.You achieve that behavior by using override to extend the base class method.

El código siguiente contiene el ejemplo completo.The following code contains the full example.

using System;  
using System.Text;  
  
namespace OverrideAndNew  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            BaseClass bc = new BaseClass();  
            DerivedClass dc = new DerivedClass();  
            BaseClass bcdc = new DerivedClass();  
  
            // The following two calls do what you would expect. They call  
            // the methods that are defined in BaseClass.  
            bc.Method1();  
            bc.Method2();  
            // Output:  
            // Base - Method1  
            // Base - Method2  
  
            // The following two calls do what you would expect. They call  
            // the methods that are defined in DerivedClass.  
            dc.Method1();  
            dc.Method2();  
            // Output:  
            // Derived - Method1  
            // Derived - Method2  
  
            // The following two calls produce different results, depending   
            // on whether override (Method1) or new (Method2) is used.  
            bcdc.Method1();  
            bcdc.Method2();  
            // Output:  
            // Derived - Method1  
            // Base - Method2  
        }  
    }  
  
    class BaseClass  
    {  
        public virtual void Method1()  
        {  
            Console.WriteLine("Base - Method1");  
        }  
  
        public virtual void Method2()  
        {  
            Console.WriteLine("Base - Method2");  
        }  
    }  
  
    class DerivedClass : BaseClass  
    {  
        public override void Method1()  
        {  
            Console.WriteLine("Derived - Method1");  
        }  
  
        public new void Method2()  
        {  
            Console.WriteLine("Derived - Method2");  
        }  
    }  
}  

En el ejemplo siguiente se muestra un comportamiento similar en un contexto diferente.The following example illustrates similar behavior in a different context. El ejemplo define tres clases: una clase base denominada Car y dos clases que se derivan de ella, ConvertibleCar y Minivan.The example defines three classes: a base class named Car and two classes that are derived from it, ConvertibleCar and Minivan. La clase base contiene un método DescribeCar.The base class contains a DescribeCar method. El método muestra una descripción básica de un automóvil y, después, llama a ShowDetails para proporcionar información adicional.The method displays a basic description of a car, and then calls ShowDetails to provide additional information. Cada una de las tres clases define un método ShowDetails.Each of the three classes defines a ShowDetails method. El modificador new se usa para definir ShowDetails en la clase ConvertibleCar.The new modifier is used to define ShowDetails in the ConvertibleCar class. El modificador override se usa para definir ShowDetails en la clase Minivan.The override modifier is used to define ShowDetails in the Minivan class.

// Define the base class, Car. The class defines two methods,  
// DescribeCar and ShowDetails. DescribeCar calls ShowDetails, and each derived  
// class also defines a ShowDetails method. The example tests which version of  
// ShowDetails is selected, the base class method or the derived class method.  
class Car  
{  
    public void DescribeCar()  
    {  
        System.Console.WriteLine("Four wheels and an engine.");  
        ShowDetails();  
    }  
  
    public virtual void ShowDetails()  
    {  
        System.Console.WriteLine("Standard transportation.");  
    }  
}  
  
// Define the derived classes.  
  
// Class ConvertibleCar uses the new modifier to acknowledge that ShowDetails  
// hides the base class method.  
class ConvertibleCar : Car  
{  
    public new void ShowDetails()  
    {  
        System.Console.WriteLine("A roof that opens up.");  
    }  
}  
  
// Class Minivan uses the override modifier to specify that ShowDetails  
// extends the base class method.  
class Minivan : Car  
{  
    public override void ShowDetails()  
    {  
        System.Console.WriteLine("Carries seven people.");  
    }  
}  

El ejemplo comprueba la versión de ShowDetails que se llama.The example tests which version of ShowDetails is called. El siguiente método, TestCars1, declara una instancia de cada clase y, después, llama a DescribeCar en cada instancia.The following method, TestCars1, declares an instance of each class, and then calls DescribeCar on each instance.

public static void TestCars1()  
{  
    System.Console.WriteLine("\nTestCars1");  
    System.Console.WriteLine("----------");  
  
    Car car1 = new Car();  
    car1.DescribeCar();  
    System.Console.WriteLine("----------");  
  
    // Notice the output from this test case. The new modifier is  
    // used in the definition of ShowDetails in the ConvertibleCar  
    // class.    
  
    ConvertibleCar car2 = new ConvertibleCar();  
    car2.DescribeCar();  
    System.Console.WriteLine("----------");  
  
    Minivan car3 = new Minivan();  
    car3.DescribeCar();  
    System.Console.WriteLine("----------");  
}  

TestCars1 genera el siguiente resultado.TestCars1 produces the following output. Observe especialmente los resultados de car2, que probablemente no son los que se esperaban.Notice especially the results for car2, which probably are not what you expected. El tipo de objeto es ConvertibleCar, pero DescribeCar no tiene acceso a la versión de ShowDetails que se define en la clase ConvertibleCar porque ese método se declara con el modificador new, no con el modificador override.The type of the object is ConvertibleCar, but DescribeCar does not access the version of ShowDetails that is defined in the ConvertibleCar class because that method is declared with the new modifier, not the override modifier. Como resultado, un objeto ConvertibleCar muestra la misma descripción que un objeto Car.As a result, a ConvertibleCar object displays the same description as a Car object. Compare los resultados de car3, que es un objeto Minivan.Contrast the results for car3, which is a Minivan object. En este caso, el método ShowDetails que se declara en la clase Minivan invalida el método ShowDetails que se declara en la clase Car, y en la descripción que se muestra se describe una furgoneta.In this case, the ShowDetails method that is declared in the Minivan class overrides the ShowDetails method that is declared in the Car class, and the description that is displayed describes a minivan.

// TestCars1  
// ----------  
// Four wheels and an engine.  
// Standard transportation.  
// ----------  
// Four wheels and an engine.  
// Standard transportation.  
// ----------  
// Four wheels and an engine.  
// Carries seven people.  
// ----------  

TestCars2 crea una lista de objetos que tienen el tipo Car.TestCars2 creates a list of objects that have type Car. Se crean instancias de los valores de los objetos desde las clases Car, ConvertibleCar y Minivan.The values of the objects are instantiated from the Car, ConvertibleCar, and Minivan classes. DescribeCar se llama en cada elemento de la lista.DescribeCar is called on each element of the list. En el código siguiente se muestra la definición de TestCars2.The following code shows the definition of TestCars2.

public static void TestCars2()  
{  
    System.Console.WriteLine("\nTestCars2");  
    System.Console.WriteLine("----------");  
  
    var cars = new List<Car> { new Car(), new ConvertibleCar(),   
        new Minivan() };  
  
    foreach (var car in cars)  
    {  
        car.DescribeCar();  
        System.Console.WriteLine("----------");  
    }  
}  

Se muestra el siguiente resultado.The following output is displayed. Observe que es el mismo resultado mostrado por TestCars1.Notice that it is the same as the output that is displayed by TestCars1. El método ShowDetails de la clase ConvertibleCar no se llama, independientemente de si el tipo de objeto es ConvertibleCar, como en TestCars1, o Car como en TestCars2.The ShowDetails method of the ConvertibleCar class is not called, regardless of whether the type of the object is ConvertibleCar, as in TestCars1, or Car, as in TestCars2. Por el contrario, car3 llama al método ShowDetails desde la clase Minivan en ambos casos, independientemente de que tenga el tipo Minivan o Car.Conversely, car3 calls the ShowDetails method from the Minivan class in both cases, whether it has type Minivan or type Car.

// TestCars2  
// ----------  
// Four wheels and an engine.  
// Standard transportation.  
// ----------  
// Four wheels and an engine.  
// Standard transportation.  
// ----------  
// Four wheels and an engine.  
// Carries seven people.  
// ----------  

Los métodos TestCars3 y TestCars4 completan el ejemplo.Methods TestCars3 and TestCars4 complete the example. Estos métodos llaman directamente a ShowDetails, primero desde los objetos declarados con el tipo ConvertibleCar y Minivan (TestCars3), y después desde los objetos declarados con el tipo Car (TestCars4).These methods call ShowDetails directly, first from objects declared to have type ConvertibleCar and Minivan (TestCars3), then from objects declared to have type Car (TestCars4). En el código siguiente se definen estos dos métodos.The following code defines these two methods.

public static void TestCars3()  
{  
    System.Console.WriteLine("\nTestCars3");  
    System.Console.WriteLine("----------");  
    ConvertibleCar car2 = new ConvertibleCar();  
    Minivan car3 = new Minivan();  
    car2.ShowDetails();  
    car3.ShowDetails();  
}  
  
public static void TestCars4()  
{  
    System.Console.WriteLine("\nTestCars4");  
    System.Console.WriteLine("----------");  
    Car car2 = new ConvertibleCar();  
    Car car3 = new Minivan();  
    car2.ShowDetails();  
    car3.ShowDetails();  
}  

Los métodos generan el siguiente resultado, que se corresponde a los resultados del primer ejemplo de este tema.The methods produce the following output, which corresponds to the results from the first example in this topic.

// TestCars3  
// ----------  
// A roof that opens up.  
// Carries seven people.  
  
// TestCars4  
// ----------  
// Standard transportation.  
// Carries seven people.  

En el código siguiente se muestra el proyecto completo y sus resultados.The following code shows the complete project and its output.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
  
namespace OverrideAndNew2  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            // Declare objects of the derived classes and test which version  
            // of ShowDetails is run, base or derived.  
            TestCars1();  
  
            // Declare objects of the base class, instantiated with the  
            // derived classes, and repeat the tests.  
            TestCars2();  
  
            // Declare objects of the derived classes and call ShowDetails  
            // directly.  
            TestCars3();  
  
            // Declare objects of the base class, instantiated with the  
            // derived classes, and repeat the tests.  
            TestCars4();  
        }  
  
        public static void TestCars1()  
        {  
            System.Console.WriteLine("\nTestCars1");  
            System.Console.WriteLine("----------");  
  
            Car car1 = new Car();  
            car1.DescribeCar();  
            System.Console.WriteLine("----------");  
  
            // Notice the output from this test case. The new modifier is  
            // used in the definition of ShowDetails in the ConvertibleCar  
            // class.    
            ConvertibleCar car2 = new ConvertibleCar();  
            car2.DescribeCar();  
            System.Console.WriteLine("----------");  
  
            Minivan car3 = new Minivan();  
            car3.DescribeCar();  
            System.Console.WriteLine("----------");  
        }  
        // Output:  
        // TestCars1  
        // ----------  
        // Four wheels and an engine.  
        // Standard transportation.  
        // ----------  
        // Four wheels and an engine.  
        // Standard transportation.  
        // ----------  
        // Four wheels and an engine.  
        // Carries seven people.  
        // ----------  
  
        public static void TestCars2()  
        {  
            System.Console.WriteLine("\nTestCars2");  
            System.Console.WriteLine("----------");  
  
            var cars = new List<Car> { new Car(), new ConvertibleCar(),   
                new Minivan() };  
  
            foreach (var car in cars)  
            {  
                car.DescribeCar();  
                System.Console.WriteLine("----------");  
            }  
        }  
        // Output:  
        // TestCars2  
        // ----------  
        // Four wheels and an engine.  
        // Standard transportation.  
        // ----------  
        // Four wheels and an engine.  
        // Standard transportation.  
        // ----------  
        // Four wheels and an engine.  
        // Carries seven people.  
        // ----------  
  
        public static void TestCars3()  
        {  
            System.Console.WriteLine("\nTestCars3");  
            System.Console.WriteLine("----------");  
            ConvertibleCar car2 = new ConvertibleCar();  
            Minivan car3 = new Minivan();  
            car2.ShowDetails();  
            car3.ShowDetails();  
        }  
        // Output:  
        // TestCars3  
        // ----------  
        // A roof that opens up.  
        // Carries seven people.  
  
        public static void TestCars4()  
        {  
            System.Console.WriteLine("\nTestCars4");  
            System.Console.WriteLine("----------");  
            Car car2 = new ConvertibleCar();  
            Car car3 = new Minivan();  
            car2.ShowDetails();  
            car3.ShowDetails();  
        }  
        // Output:  
        // TestCars4  
        // ----------  
        // Standard transportation.  
        // Carries seven people.  
    }  
  
    // Define the base class, Car. The class defines two virtual methods,  
    // DescribeCar and ShowDetails. DescribeCar calls ShowDetails, and each derived  
    // class also defines a ShowDetails method. The example tests which version of  
    // ShowDetails is used, the base class method or the derived class method.  
    class Car  
    {  
        public virtual void DescribeCar()  
        {  
            System.Console.WriteLine("Four wheels and an engine.");  
            ShowDetails();  
        }  
  
        public virtual void ShowDetails()  
        {  
            System.Console.WriteLine("Standard transportation.");  
        }  
    }  
  
    // Define the derived classes.  
  
    // Class ConvertibleCar uses the new modifier to acknowledge that ShowDetails  
    // hides the base class method.  
    class ConvertibleCar : Car  
    {  
        public new void ShowDetails()  
        {  
            System.Console.WriteLine("A roof that opens up.");  
        }  
    }  
  
    // Class Minivan uses the override modifier to specify that ShowDetails  
    // extends the base class method.  
    class Minivan : Car  
    {  
        public override void ShowDetails()  
        {  
            System.Console.WriteLine("Carries seven people.");  
        }  
    }  
  
}  

Vea tambiénSee also