Sdílet prostřednictvím


Vědět kdy použít klíčová slova override a new (Průvodce programováním v C#)

V jazyce C# může mít metoda v odvozené třídě stejný název jako metoda v základní třídě. Můžete určit, jak metody spolu interagují, pomocí klíčových slov new a override. override Modifikátor rozšiřuje metodu základní třídy virtual a new modifikátor skryje přístupnou metodu základní třídy. Rozdíl je znázorněn v příkladech v tomto tématu.

V konzolové aplikaci deklarujte následující dvě třídy BaseClass a DerivedClass. DerivedClass dědí z BaseClass.

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

Main V metodě deklarujte proměnné bc, dca bcdc.

  • bc je typu BaseClassa jeho hodnota je typu BaseClass.

  • dc je typu DerivedClassa jeho hodnota je typu DerivedClass.

  • bcdc je typu BaseClassa jeho hodnota je typu DerivedClass. Jedná se o proměnnou, na které je potřeba věnovat pozornost.

Protože bc a bcdc mají typ BaseClass, mají pouze přímý přístup k Method1, ledaže používáte přetypování. Proměnná dc má přístup k oběma Method1 a Method2. Tyto relace se zobrazují v následujícím kódu.

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  
}  

Dále přidejte následující Method2 metodu do BaseClasssouboru . Podpis této metody odpovídá podpisu Method2 metody v DerivedClass.

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

Vzhledem k tomu, že BaseClass nyní má metodu Method2, lze přidat druhý volací příkaz pro proměnné BaseClass, bc a bcdc, jak je znázorněno v následujícím kódu.

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

Nové klíčové slovo

Když sestavíte projekt, uvidíte, že přidání metody Method2 v BaseClass způsobuje upozornění. Upozornění říká, že Method2 metoda v DerivedClass skrytí Method2 metody v BaseClass. Pokud chcete tento výsledek způsobit, doporučujeme použít new klíčové slovo v Method2 definici. Alternativně můžete přejmenovat některou z Method2 metod pro vyřešení upozornění, ale to není vždy praktické.

Před přidáním newspusťte program a zobrazte výstup vytvořený dalšími příkazy volání. Zobrazí se následující výsledky.

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

Klíčové new slovo zachovává relace, které tento výstup vytvoří, ale potlačí upozornění. Proměnné, které mají typ BaseClass, nadále přistupují ke členům BaseClass, a proměnná, která má typ DerivedClass, nejprve přistupuje k členům DerivedClass a pak zvažuje členy zděděné z BaseClass.

Chcete-li potlačit upozornění, přidejte new modifikátor do definice Method2 in DerivedClass, jak je znázorněno v následujícím kódu. Modifikátor lze přidat před nebo za public.

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

Spusťte program znovu a ověřte, že se výstup nezměnil. Ověřte také, že se upozornění už nezobrazuje. Pomocí new tvrdíte, že si uvědomujete, že člen, který upravujete, skrývá člena zděděného ze základní třídy. Další informace o skrytí jména prostřednictvím dědičnosti naleznete v novém Modifikátoru.

Klíčová slova virtuální a překračování

Chcete-li toto chování kontrastovat s účinky použití override, přidejte následující metodu do DerivedClass. override Modifikátor lze přidat před nebo za public.

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

Přidejte modifikátor virtual do definice Method1 v BaseClass. virtual Modifikátor lze přidat před nebo za public.

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

Spusťte projekt znovu. Všimněte si zejména posledních dvou řádků následujícího výstupu.

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

Použití modifikátoru override umožňuje bcdc přístup k Method1 metodě, která je definována v DerivedClass. Obvykle se jedná o požadované chování v hierarchiích dědičnosti. Chcete, aby objekty, které mají hodnoty vytvořené z odvozené třídy, používaly metody definované v odvozené třídě. Toto chování dosáhnete použitím override k rozšíření metody základní třídy.

Následující kód obsahuje úplný příklad.

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");  
        }  
    }  
}  

Přepsání a nové v odvozených třídách

Následující příklad ukazuje podobné chování v jiném kontextu. Příklad definuje tři třídy: základní třídu pojmenovanou Car a dvě třídy odvozené z ní ConvertibleCar a Minivan. Základní třída obsahuje metodu DescribeCar . Tato metoda zobrazí základní popis auta a potom zavolá ShowDetails, aby poskytla další informace. Každá ze tří tříd definuje metodu ShowDetails . new Modifikátor se používá k definování ShowDetails ve ConvertibleCar třídě. override Modifikátor se používá k definování ShowDetails ve Minivan třídě.

// 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.");  
    }  
}  

Testovací příklady, která verze ShowDetails se volá. Následující metoda , TestCars1deklaruje instanci každé třídy a potom volá DescribeCar na každou instanci.

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.
  
    Car car2 = new ConvertibleCar();  
    car2.DescribeCar();  
    System.Console.WriteLine("----------");  
  
    Minivan car3 = new Minivan();  
    car3.DescribeCar();  
    System.Console.WriteLine("----------");  
}  

TestCars1 vytvoří následující výstup. Všimněte si zejména výsledků car2, které pravděpodobně nejsou to, co jste očekávali. Typ objektu je ConvertibleCar, ale DescribeCar nemá přístup k verzi ShowDetails, která je definována ve třídě ConvertibleCar, protože tato metoda je deklarována s new modifikátorem, nikoli s override modifikátorem. V důsledku toho ConvertibleCar objekt zobrazí stejný popis jako Car objekt. Porovnejte výsledky pro car3, což je Minivan objekt. V tomto případě metoda deklarovaná ShowDetails ve Minivan třídě přepíše ShowDetails metodu deklarovanou ve Car třídě a popis zobrazený popis popisuje 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 vytvoří seznam objektů, které mají typ Car. Hodnoty objektů jsou instanciovány z tříd Car, ConvertibleCar a Minivan. DescribeCar je aplikována na každý prvek seznamu. Následující kód ukazuje definici .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("----------");  
    }  
}  

Zobrazí se následující výstup. Všimněte si, že jde o stejný výstup, který je zobrazen pomocí TestCars1. Metoda ShowDetailsConvertibleCar třídy není volána bez ohledu na to, zda typ objektu je ConvertibleCar, jako v TestCars1, nebo Car, jako v TestCars2. Naopak car3 volá metodu ShowDetails třídy Minivan v obou případech, ať už má typ Minivan nebo 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 a TestCars4 doplňují příklad. Tyto metody volají ShowDetails přímo, nejprve z objektů deklarovaných jako typ ConvertibleCar a Minivan (TestCars3), pak z objektů deklarovaných jako typ Car (TestCars4). Následující kód definuje tyto dvě metody.

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 vytvoří následující výstup, který odpovídá výsledkům z prvního příkladu v tomto tématu.

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

Následující kód ukazuje úplný projekt a jeho výstup.

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.");  
        }  
    }  
  
}  

Viz také