Quando usar as palavras-chave override e new (Guia de Programação em C#)Knowing When to Use Override and New Keywords (C# Programming Guide)

No C#, um método em uma classe derivada pode ter o mesmo nome que um método na classe base.In C#, a method in a derived class can have the same name as a method in the base class. É possível especificar a maneira como os métodos interagem usando as palavras-chave new e override.You can specify how the methods interact by using the new and override keywords. O modificador override estende o método virtual da classe base e o modificadornew oculta um método de classe base acessível.The override modifier extends the base class virtual method, and the new modifier hides an accessible base class method. A diferença é ilustrada nos exemplos deste tópico.The difference is illustrated in the examples in this topic.

Em um aplicativo de console, declare as duas classes a seguir, BaseClass e DerivedClass.In a console application, declare the following two classes, BaseClass and DerivedClass. DerivedClass herda 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");  
    }  
}  

No método Main, declare as variáveis bc, dc e bcdc.In the Main method, declare variables bc, dc, and bcdc.

  • bc é do tipo BaseClass e seu valor é do tipo BaseClass.bc is of type BaseClass, and its value is of type BaseClass.

  • dc é do tipo DerivedClass e seu valor é do tipo DerivedClass.dc is of type DerivedClass, and its value is of type DerivedClass.

  • bcdc é do tipo BaseClass e seu valor é do tipo DerivedClass.bcdc is of type BaseClass, and its value is of type DerivedClass. Essa é a variável à qual você deve prestar atenção.This is the variable to pay attention to.

Como bc e bcdc têm o tipo BaseClass, eles podem ter acesso direto a Method1, a menos que você usa a conversão.Because bc and bcdc have type BaseClass, they can only directly access Method1, unless you use casting. A variável dc pode acessar Method1 e Method2.Variable dc can access both Method1 and Method2. Essas relações são mostradas no código a seguir.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  
}  

Em seguida, adicione o seguinte método Method2 a BaseClass.Next, add the following Method2 method to BaseClass. A assinatura desse método corresponde à assinatura do método Method2 em DerivedClass.The signature of this method matches the signature of the Method2 method in DerivedClass.

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

Como BaseClass agora tem um método Method2, uma segunda instrução de chamada pode ser adicionada para variáveis de BaseClass bc e bcdc, conforme mostrado no código a seguir.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();  

Quando você compilar o projeto, verá que a adição do método Method2 gera um aviso BaseClass.When you build the project, you see that the addition of the Method2 method in BaseClass causes a warning. O aviso informa que o método Method2 em DerivedClass oculta o método Method2 em BaseClass.The warning says that the Method2 method in DerivedClass hides the Method2 method in BaseClass. É recomendável usar a palavra-chave new na definição Method2 se você pretende gerar esse resultado.You are advised to use the new keyword in the Method2 definition if you intend to cause that result. Como alternativa, seria possível renomear um dos métodos Method2 para resolver o aviso, mas isso nem sempre é prático.Alternatively, you could rename one of the Method2 methods to resolve the warning, but that is not always practical.

Antes de adicionar new, execute o programa para ver a saída produzida pelas outras instruções de chamada.Before adding new, run the program to see the output produced by the additional calling statements. Os seguintes resultados são exibidos.The following results are displayed.

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

A palavra-chave new preserva as relações que produzem essa saída, mas suprime o aviso.The new keyword preserves the relationships that produce that output, but it suppresses the warning. As variáveis que têm o tipo BaseClass continuam acessando os membros de BaseClass e a variável que tem o tipo DerivedClass continua acessando os membros em DerivedClass primeiro e, em seguida, considera os membros herdados 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 o aviso, adicione o modificador new para a definição de Method2 em DerivedClass, conforme mostrado no código a seguir.To suppress the warning, add the new modifier to the definition of Method2 in DerivedClass, as shown in the following code. O modificador pode ser adicionado antes ou depois de public.The modifier can be added before or after public.

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

Execute o programa novamente para verificar se a saída não foi alterada.Run the program again to verify that the output has not changed. Verifique também se o aviso não é mais exibido.Also verify that the warning no longer appears. Usando new, você está declarando que está ciente de que o membro que ele modifica oculta um membro herdado da classe 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 obter mais informações sobre a ocultação de nome por meio de herança, consulte Novo modificador.For more information about name hiding through inheritance, see new Modifier.

Para comparar esse comportamento com os efeitos de usar override, adicione o seguinte método a DerivedClass.To contrast this behavior to the effects of using override, add the following method to DerivedClass. O modificador override pode ser adicionado antes ou depois de public.The override modifier can be added before or after public.

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

Adicione o modificador virtual à definição de Method1 em BaseClass.Add the virtual modifier to the definition of Method1 in BaseClass. O modificador virtual pode ser adicionado antes ou depois de public.The virtual modifier can be added before or after public.

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

Execute o projeto novamente.Run the project again. Observe principalmente as duas últimas linhas da saída a seguir.Notice especially the last two lines of the following output.

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

O uso do modificador override permite que bcdc acesse o método Method1 definido em DerivedClass.The use of the override modifier enables bcdc to access the Method1 method that is defined in DerivedClass. Normalmente, esse é o comportamento desejado em hierarquias de herança.Typically, that is the desired behavior in inheritance hierarchies. Você quer objetos com valores criados da classe derivada para usar os métodos definidos na classe 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. Obtenha esse comportamento usando override para estender o método da classe base.You achieve that behavior by using override to extend the base class method.

O código a seguir contem o exemplo 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");  
        }  
    }  
}  

O exemplo a seguir ilustra um comportamento semelhante em um contexto diferente.The following example illustrates similar behavior in a different context. O exemplo define três classes: uma classe base chamada Car e duas classes derivadas dela, ConvertibleCar e Minivan.The example defines three classes: a base class named Car and two classes that are derived from it, ConvertibleCar and Minivan. A classe base contém um método DescribeCar.The base class contains a DescribeCar method. O método exibe uma descrição básica de um carro e, em seguida, chama ShowDetails para fornecer mais informações.The method displays a basic description of a car, and then calls ShowDetails to provide additional information. Cada uma das três classes define um método ShowDetails.Each of the three classes defines a ShowDetails method. O modificador new é usado para definir ShowDetails na classe ConvertibleCar.The new modifier is used to define ShowDetails in the ConvertibleCar class. O modificador override é usado para definir ShowDetails na classe 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.");  
    }  
}  

O exemplo testa qual versão do ShowDetails é chamada.The example tests which version of ShowDetails is called. O método a seguir, TestCars1, declara uma instância de cada classe e, em seguida, chama DescribeCar em cada instância.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 produz a saída a seguir.TestCars1 produces the following output. Observe principalmente os resultados para car2, que provavelmente não são o que você espera.Notice especially the results for car2, which probably are not what you expected. O tipo do objeto é ConvertibleCar, mas DescribeCar não acessa a versão de ShowDetails definida na classe ConvertibleCar, porque esse método é declarado com o modificador new, e não com o 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. Em decorrência disso, um objeto ConvertibleCar exibe a mesma descrição que um objeto Car.As a result, a ConvertibleCar object displays the same description as a Car object. Compare os resultados de car3, que é um objeto Minivan.Contrast the results for car3, which is a Minivan object. Nesse caso, o método ShowDetails declarado na classe Minivan substitui o método ShowDetails declarado na classe Car e a descrição exibida descreve uma minivan.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 cria uma lista de objetos que têm tipo Car.TestCars2 creates a list of objects that have type Car. Os valores dos objetos são instanciados com base nas classes Car, ConvertibleCar e Minivan.The values of the objects are instantiated from the Car, ConvertibleCar, and Minivan classes. DescribeCar é chamado em cada elemento da lista.DescribeCar is called on each element of the list. O código a seguir mostra a definição 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("----------");  
    }  
}  

É exibida a saída a seguir.The following output is displayed. Observe que é a mesma que a saída exibida por TestCars1.Notice that it is the same as the output that is displayed by TestCars1. O método ShowDetails da classe ConvertibleCar não é chamado, independentemente se o tipo do objeto é ConvertibleCar, como em TestCars1 ou Car, como em 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 outro lado, car3 chama o método ShowDetails com base na classe Minivan nos dois casos, tendo ele o tipo Minivan ou o tipo 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.  
// ----------  

Os métodos TestCars3 e TestCars4 completam o exemplo.Methods TestCars3 and TestCars4 complete the example. Esses métodos chamam ShowDetails diretamente, primeiro com base nos objetos declarados para ter o tipo ConvertibleCar e Minivan (TestCars3), em seguida, com base nos objetos declarados para ter o 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). O código a seguir define esses dois 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();  
}  

Os métodos produzem a saída a seguir, que corresponde aos resultados do primeiro exemplo neste tópico.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.  

O código a seguir mostra o projeto completo e sua saída.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.");  
        }  
    }  
  
}  

Consulte tambémSee also