Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Em C#, um método em uma classe derivada pode ter o mesmo nome de um método na classe base. Você pode especificar como os métodos interagem usando as palavras-chave novas e substituídas . O override
modificador estende o método de classe virtual
base e o new
modificador oculta um método de classe base acessível. A diferença é ilustrada nos exemplos deste tópico.
Em um aplicativo de console, declare as duas classes BaseClass
a seguir e DerivedClass
.
DerivedClass
herda de BaseClass
.
class BaseClass
{
public void Method1()
{
Console.WriteLine("Base - Method1");
}
}
class DerivedClass : BaseClass
{
public void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
Main
No método, declare variáveis bc
e dc
bcdc
.
bc
é do tipoBaseClass
, e seu valor é do tipoBaseClass
.dc
é do tipoDerivedClass
, e seu valor é do tipoDerivedClass
.bcdc
é do tipoBaseClass
, e seu valor é do tipoDerivedClass
. Essa é a variável à qual prestar atenção.
Como bc
e bcdc
têm o tipo BaseClass
, eles podem ter acesso direto a Method1
, a menos que você usa a conversão. A variável dc
pode acessar ambos Method1
e Method2
. Essas relações são mostradas no código a seguir.
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 método a seguir Method2
a BaseClass
. A assinatura desse método corresponde à assinatura do Method2
método em DerivedClass
.
public void Method2()
{
Console.WriteLine("Base - Method2");
}
Como BaseClass
agora tem um Method2
método, uma segunda instrução de chamada pode ser adicionada para BaseClass
variáveis bc
e bcdc
, conforme mostrado no código a seguir.
bc.Method1();
bc.Method2();
dc.Method1();
dc.Method2();
bcdc.Method1();
bcdc.Method2();
Ao compilar o projeto, você verá que a adição do método Method2
em BaseClass
causa um aviso. O aviso diz que o Method2
método em DerivedClass
oculta o Method2
método em BaseClass
. Recomenda-se usar a palavra-chave new
na definição Method2
se você pretende causar esse resultado. Como alternativa, você pode renomear um dos Method2
métodos para resolver o aviso, mas isso nem sempre é prático.
Antes de adicionar new
, execute o programa para ver a saída produzida pelas instruções de chamada adicionais. Os resultados a seguir são exibidos.
// Output:
// Base - Method1
// Base - Method2
// Base - Method1
// Derived - Method2
// Base - Method1
// Base - Method2
A new
palavra-chave preserva as relações que produzem essa saída, mas suprime o aviso. As variáveis que têm tipo BaseClass
continuam a acessar os membros de BaseClass
, e a variável que tem tipo DerivedClass
continua a acessar os membros em DerivedClass
primeiro, e então considerar os membros herdados de BaseClass
.
Para suprimir o aviso, adicione o modificador new
à definição de Method2
em DerivedClass
, conforme mostrado no código a seguir. O modificador pode ser adicionado antes ou depois public
.
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
Execute o programa novamente para verificar se a saída não foi alterada. Verifique também se o aviso não é mais exibido. Ao usar new
, você está afirmando que está ciente de que o membro que ele modifica oculta um membro herdado da classe base. Para obter mais informações sobre o ocultamento de nome por meio da herança, consulte o novo Modificador.
Para contrastar esse comportamento com os efeitos do uso override
, adicione o método a seguir a DerivedClass
. O override
modificador pode ser adicionado antes ou depois public
.
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
Adicione o virtual
modificador à definição de Method1
em BaseClass
. O virtual
modificador pode ser adicionado antes ou depois public
.
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
Execute o projeto novamente. Observe principalmente as duas últimas linhas da saída a seguir.
// Output:
// Base - Method1
// Base - Method2
// Derived - Method1
// Derived - Method2
// Derived - Method1
// Base - Method2
O uso do override
modificador permite bcdc
acessar o Method1
método definido em DerivedClass
. Normalmente, esse é o comportamento desejado nas hierarquias de herança. Você deseja que os objetos que têm valores criados a partir da classe derivada usem os métodos definidos na classe derivada. Você obtém esse comportamento usando override
para estender o método de classe base.
O código a seguir contém o exemplo completo.
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. O exemplo define três classes: uma classe base nomeada Car
e duas classes derivadas dela e ConvertibleCar
Minivan
. A classe base contém um DescribeCar
método. O método exibe uma descrição básica de um carro e, em seguida, chama ShowDetails
para fornecer informações adicionais. Cada uma das três classes define um ShowDetails
método. O new
modificador é usado para definir ShowDetails
na ConvertibleCar
classe. O override
modificador é usado para definir ShowDetails
na Minivan
classe.
// 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 de ShowDetails
é chamada. O método a seguir, TestCars1
, declara uma instância de cada classe e, em seguida, chama DescribeCar
em cada instância.
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. Observe especialmente os resultados para car2
, que provavelmente não são o que você esperava. O tipo do objeto é ConvertibleCar
, mas DescribeCar
não acessa a versão do ShowDetails
que é definido na ConvertibleCar
classe porque esse método é declarado com o new
modificador, não com o override
modificador. Como resultado, um ConvertibleCar
objeto exibe a mesma descrição de um Car
objeto. Contraste os resultados para car3
, que é um objeto Minivan
. Nesse caso, o ShowDetails
método declarado na Minivan
classe substitui o ShowDetails
método que é declarado na Car
classe e a descrição exibida descreve uma 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 o tipo Car
. Os valores dos objetos são instanciados das classes Car
, ConvertibleCar
, e Minivan
.
DescribeCar
é aplicado a cada elemento da lista. O código a seguir mostra a definição de 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("----------");
}
}
O resultado a seguir é exibido. Observe que é o mesmo que a saída exibida por TestCars1
. O ShowDetails
método da ConvertibleCar
classe não é chamado, independentemente de o tipo do objeto ser ConvertibleCar
, como em TestCars1
, ou Car
, como em TestCars2
. Por outro lado, car3
chama o método ShowDetails
da classe Minivan
em ambos os casos, independentemente de ser do tipo Minivan
ou do tipo Car
.
// TestCars2
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Carries seven people.
// ----------
Métodos TestCars3
e TestCars4
concluem o exemplo. Esses métodos chamam ShowDetails
diretamente, primeiro de objetos declarados para ter tipo ConvertibleCar
e Minivan
(TestCars3
), em seguida, de objetos declarados para ter tipo Car
(TestCars4
). O código a seguir define esses dois métodos.
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.
// 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.
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.");
}
}
}