Użycie przesłonięć i nowych słów kluczowych (Przewodnik programowania w języku C#)Knowing When to Use Override and New Keywords (C# Programming Guide)

W C#programie Metoda w klasie pochodnej może mieć taką samą nazwę jak metoda w klasie bazowej.In C#, a method in a derived class can have the same name as a method in the base class. Możesz określić sposób działania metod przy użyciu słów kluczowych New i override .You can specify how the methods interact by using the new and override keywords. Modyfikator override rozszerza metodę klasy bazowej virtual, a modyfikator new ukrywa dostępną metodę klasy bazowej.The override modifier extends the base class virtual method, and the new modifier hides an accessible base class method. Różnica przedstawiono w przykładach w tym temacie.The difference is illustrated in the examples in this topic.

W aplikacji konsoli Zadeklaruj poniższe dwie klasy BaseClass i DerivedClass.In a console application, declare the following two classes, BaseClass and DerivedClass. DerivedClass dziedziczy z BaseClass.DerivedClass inherits from BaseClass.

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

W metodzie Main Zadeklaruj zmienne bc, dci bcdc.In the Main method, declare variables bc, dc, and bcdc.

  • bc jest typu BaseClass, a jego wartość jest typu BaseClass.bc is of type BaseClass, and its value is of type BaseClass.

  • dc jest typu DerivedClass, a jego wartość jest typu DerivedClass.dc is of type DerivedClass, and its value is of type DerivedClass.

  • bcdc jest typu BaseClass, a jego wartość jest typu DerivedClass.bcdc is of type BaseClass, and its value is of type DerivedClass. Jest to zmienna, do której należy zwrócić uwagę.This is the variable to pay attention to.

Ponieważ bc i bcdc mają BaseClasstypu, mogą bezpośrednio uzyskać dostęp do Method1, chyba że używasz rzutowania.Because bc and bcdc have type BaseClass, they can only directly access Method1, unless you use casting. Zmienna dc ma dostęp do Method1 i Method2.Variable dc can access both Method1 and Method2. Te relacje są pokazane w poniższym kodzie.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  
}  

Następnie Dodaj następującą metodę Method2, aby BaseClass.Next, add the following Method2 method to BaseClass. Podpis tej metody pasuje do sygnatury metody Method2 w DerivedClass.The signature of this method matches the signature of the Method2 method in DerivedClass.

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

Ponieważ BaseClass teraz ma metodę Method2, druga instrukcja wywołująca może zostać dodana dla zmiennych BaseClass bc i bcdc, jak pokazano w poniższym kodzie.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();  

Podczas kompilowania projektu, zobaczysz, że dodanie metody Method2 w BaseClass powoduje ostrzeżenie.When you build the project, you see that the addition of the Method2 method in BaseClass causes a warning. Ostrzeżenie informuje, że metoda Method2 w DerivedClass ukrywa metodę Method2 w BaseClass.The warning says that the Method2 method in DerivedClass hides the Method2 method in BaseClass. Zaleca się użycie słowa kluczowego new w definicji Method2, jeśli zamierzasz mieć ten wynik.You are advised to use the new keyword in the Method2 definition if you intend to cause that result. Alternatywnie można zmienić nazwę jednej z Method2 metod, aby rozwiązać ostrzeżenie, ale nie zawsze jest to praktycznie możliwe.Alternatively, you could rename one of the Method2 methods to resolve the warning, but that is not always practical.

Przed dodaniem newUruchom program, aby zobaczyć dane wyjściowe generowane przez dodatkowe instrukcje wywoływania.Before adding new, run the program to see the output produced by the additional calling statements. Zostaną wyświetlone następujące wyniki.The following results are displayed.

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

Słowo kluczowe new zachowuje relacje, które tworzą dane wyjściowe, ale pomija ostrzeżenie.The new keyword preserves the relationships that produce that output, but it suppresses the warning. Zmienne, które mają typ BaseClass nadal mają dostęp do elementów członkowskich BaseClass, a zmienna, która ma typ DerivedClass nadal uzyskuje dostęp do elementów członkowskich w DerivedClass, a następnie do rozważania członków dziedziczonych z 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.

Aby pominąć ostrzeżenie, Dodaj modyfikator new do definicji Method2 w DerivedClass, jak pokazano w poniższym kodzie.To suppress the warning, add the new modifier to the definition of Method2 in DerivedClass, as shown in the following code. Modyfikator można dodać przed lub po public.The modifier can be added before or after public.

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

Ponownie uruchom program, aby sprawdzić, czy dane wyjściowe nie uległy zmianie.Run the program again to verify that the output has not changed. Sprawdź również, czy ostrzeżenie nie jest już wyświetlane.Also verify that the warning no longer appears. Korzystając z new, potwierdzasz, że użytkownik, który modyfikuje, ukrywa element członkowski, który jest Dziedziczony z klasy bazowej.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. Aby uzyskać więcej informacji na temat ukrywania nazw poprzez dziedziczenie, zobacz New modyfikator.For more information about name hiding through inheritance, see new Modifier.

Aby w przeciwieństwie do efektów używania override, należy dodać następującą metodę do DerivedClass.To contrast this behavior to the effects of using override, add the following method to DerivedClass. Modyfikator override można dodać przed publiclub po nim.The override modifier can be added before or after public.

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

Dodaj modyfikator virtual do definicji Method1 w BaseClass.Add the virtual modifier to the definition of Method1 in BaseClass. Modyfikator virtual można dodać przed publiclub po nim.The virtual modifier can be added before or after public.

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

Uruchom ponownie projekt.Run the project again. Zwróć uwagę na szczególnie ostatnie dwa wiersze następujących danych wyjściowych.Notice especially the last two lines of the following output.

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

Użycie modyfikatora override umożliwia bcdc dostępu do metody Method1 zdefiniowanej w DerivedClass.The use of the override modifier enables bcdc to access the Method1 method that is defined in DerivedClass. Zwykle jest to wymagane zachowanie w hierarchiach dziedziczenia.Typically, that is the desired behavior in inheritance hierarchies. Obiekty mające wartości, które są tworzone na podstawie klasy pochodnej, są używane do używania metod, które są zdefiniowane w klasie pochodnej.You want objects that have values that are created from the derived class to use the methods that are defined in the derived class. W tym celu należy użyć override, aby zwiększyć metodę klasy bazowej.You achieve that behavior by using override to extend the base class method.

Poniższy kod zawiera pełny przykład.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");  
        }  
    }  
}  

Poniższy przykład ilustruje podobne zachowanie w innym kontekście.The following example illustrates similar behavior in a different context. W przykładzie zdefiniowano trzy klasy: Klasa bazowa o nazwie Car i dwie klasy, które pochodzą od niej, ConvertibleCar i Minivan.The example defines three classes: a base class named Car and two classes that are derived from it, ConvertibleCar and Minivan. Klasa bazowa zawiera metodę DescribeCar.The base class contains a DescribeCar method. Metoda wyświetla podstawowy opis samochodu, a następnie wywołuje ShowDetails, aby uzyskać dodatkowe informacje.The method displays a basic description of a car, and then calls ShowDetails to provide additional information. Każda z tych trzech klas definiuje metodę ShowDetails.Each of the three classes defines a ShowDetails method. Modyfikator new służy do definiowania ShowDetails w klasie ConvertibleCar.The new modifier is used to define ShowDetails in the ConvertibleCar class. Modyfikator override służy do definiowania ShowDetails w klasie 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.");  
    }  
}  

Przykład sprawdza, która wersja ShowDetails jest wywoływana.The example tests which version of ShowDetails is called. Poniższa metoda, TestCars1, deklaruje wystąpienie każdej klasy, a następnie wywołuje DescribeCar dla każdego wystąpienia.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 generuje następujące dane wyjściowe.TestCars1 produces the following output. Zwróć uwagę na szczególnie wyniki car2, które prawdopodobnie nie są oczekiwane.Notice especially the results for car2, which probably are not what you expected. Typ obiektu jest ConvertibleCar, ale DescribeCar nie uzyskuje dostępu do wersji ShowDetails zdefiniowanej w klasie ConvertibleCar, ponieważ ta metoda jest zadeklarowana z modyfikatorem new, a nie modyfikatorem 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. W związku z tym obiekt ConvertibleCar wyświetla ten sam opis, co obiekt Car.As a result, a ConvertibleCar object displays the same description as a Car object. Należy odróżniać wyniki car3, który jest obiektem Minivan.Contrast the results for car3, which is a Minivan object. W takim przypadku Metoda ShowDetails zadeklarowana w klasie Minivan przesłania metodę ShowDetails, która jest zadeklarowana w klasie Car, a opis wyświetlany opisuje 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 tworzy listę obiektów, które mają Cartypu.TestCars2 creates a list of objects that have type Car. Wartości obiektów są tworzone na podstawie klas Car, ConvertibleCari Minivan.The values of the objects are instantiated from the Car, ConvertibleCar, and Minivan classes. DescribeCar jest wywoływana dla każdego elementu listy.DescribeCar is called on each element of the list. Poniższy kod przedstawia definicję 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("----------");  
    }  
}  

Wyświetlane są następujące dane wyjściowe.The following output is displayed. Zwróć uwagę, że jest to taka sama jak wartość wyjściowa wyświetlana przez TestCars1.Notice that it is the same as the output that is displayed by TestCars1. Metoda ShowDetails klasy ConvertibleCar nie jest wywoływana, niezależnie od tego, czy typ obiektu jest ConvertibleCar, jak w TestCars1, czy Car, jak w 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. Z kolei car3 wywołuje metodę ShowDetails z klasy Minivan w obu przypadkach, niezależnie od tego, czy ma Minivan typu, czy typu 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.  
// ----------  

Metody TestCars3 i TestCars4 wykonania przykładu.Methods TestCars3 and TestCars4 complete the example. Te metody wywołują ShowDetails bezpośrednio, najpierw z obiektów zadeklarowanych do typu ConvertibleCar i Minivan (TestCars3), a następnie z obiektów zadeklarowanych do typu 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). Poniższy kod definiuje te dwie metody.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();  
}  

Metody te generują następujące dane wyjściowe, które odpowiadają wynikom z pierwszego przykładu w tym temacie.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.  

Poniższy kod przedstawia kompletny projekt i jego dane wyjściowe.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.");  
        }  
    }  
  
}  

Zobacz takżeSee also