Megosztás a következőn keresztül:


A felülbírálás és az új kulcsszavak használatának ismerete (C# programozási útmutató)

A C#-ban egy származtatott osztály metódusának neve megegyezhet az alaposztály metódusával. Az új és felülbírálási kulcsszavak használatával megadhatja, hogyan működnek a metódusok. A override módosító kibővíti az alaposztály virtual metódusát, a new módosító pedig elrejt egy akadálymentes alaposztály-metódust . A különbséget a jelen témakör példái szemléltetik.

Egy konzolalkalmazásban deklarálja a következő két osztályt és BaseClassDerivedClass. DerivedClass örökli a .-tól BaseClass.

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

A metódusban deklarálja a Main változókat bc, dcés bcdc.

  • bc típusú BaseClass, értéke pedig típus BaseClass.

  • dc típusú DerivedClass, értéke pedig típus DerivedClass.

  • bcdc típusú BaseClass, értéke pedig típus DerivedClass. Erre a változóra kell figyelni.

Mert bc és bcdc van típusuk BaseClass, csak közvetlenül férhetnek hozzá Method1, kivéve, ha öntvényt használ. A változó dc mindkét Method1 és Method2a . Ezek a kapcsolatok az alábbi kódban jelennek meg.

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  
}  

Ezután adja hozzá a következő Method2 metódust a következőhöz BaseClass. A metódus aláírása megegyezik a metódus DerivedClassaláírásával.Method2

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

Mivel BaseClass most már van egy Method2 metódusa, egy második hívási utasítás is hozzáadható a változókhoz BaseClassbc , és bcdcaz alábbi kódban látható módon.

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

A projekt létrehozásakor láthatja, hogy a Method2 metódus BaseClass hozzáadása figyelmeztetést okoz. A figyelmeztetés azt jelzi, hogy a Method2 benne lévő DerivedClass metódus elrejti a metódust a Method2 következőben BaseClass: . Javasoljuk, hogy használja a kulcsszót new a Method2 definícióban, ha ezt az eredményt szeretné eredményezni. Másik lehetőségként átnevezheti az egyik metódust a Method2 figyelmeztetés feloldásához, de ez nem mindig praktikus.

A hozzáadás newelőtt futtassa a programot a további hívási utasítások által előállított kimenet megtekintéséhez. A következő eredmények jelennek meg.

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

A new kulcsszó megőrzi azokat a kapcsolatokat, amelyek ezt a kimenetet eredményezik, de elnyomja a figyelmeztetést. A típussal BaseClass rendelkező változók továbbra is hozzáférnek a tagokhoz BaseClass, a típussal DerivedClass rendelkező változó pedig először továbbra is a tagokhoz DerivedClass fér hozzá, majd figyelembe veszi az örökölt BaseClasstagokat.

A figyelmeztetés mellőzéséhez adja hozzá a new módosítót a következő kódban látható definícióhoz Method2DerivedClass. A módosító a következő előtt vagy után publicadható hozzá.

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

Futtassa újra a programot annak ellenőrzéséhez, hogy a kimenet nem változott-e. Ellenőrizze azt is, hogy a figyelmeztetés már nem jelenik-e meg. Ezzel newazt állítja, hogy tisztában van azzal, hogy az általa módosított tag elrejti az alaposztálytól öröklő tagot. Az öröklés során elrejtett névvel kapcsolatos további információkért lásd az új módosítót.

Ha ezt a viselkedést a használat overridehatásaival szeretné ellentétbe helyezni, adja hozzá a következő metódust.DerivedClass A override módosító a következő előtt vagy után publicadható hozzá.

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

Adja hozzá a virtual módosítót a következő definícióhozBaseClassMethod1: A virtual módosító a következő előtt vagy után publicadható hozzá.

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

Futtassa ismét a projektet. Figyelje meg különösen az alábbi kimenet utolsó két sorát.

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

A módosító override használata lehetővé teszi bcdc a Method1 /> által definiált DerivedClassmetódus elérését. Általában ez a kívánt viselkedés az öröklési hierarchiákban. Azt szeretné, hogy a származtatott osztályból létrehozott értékekkel rendelkező objektumok a származtatott osztályban definiált metódusokat használják. Ezt a viselkedést az alaposztály-metódus kibővítésével override érheti el.

Az alábbi kód a teljes példát tartalmazza.

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

Az alábbi példa egy másik kontextus hasonló viselkedését szemlélteti. A példa három osztályt határoz meg: egy névvel ellátott Car alaposztályt és két abból származtatott osztályt és MinivanConvertibleCar . Az alaposztály tartalmaz egy metódust DescribeCar . A metódus megjeleníti az autó alapszintű leírását, majd meghívja ShowDetails a további információk megadására. A három osztály mindegyike meghatároz egy metódust ShowDetails . A new módosító az ShowDetails osztályban definiálható ConvertibleCar . A override módosító az ShowDetails osztályban definiálható Minivan .

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

A példa azt teszteli, hogy a rendszer melyik verziót ShowDetails hívja meg. Az alábbi metódus TestCars1az egyes osztályok egy-egy példányát deklarálja, majd meghívja DescribeCar az egyes példányokat.

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 a következő kimenetet állítja elő. Figyelje meg különösen az eredményeket car2, amelyek valószínűleg nem az, amit várt. Az objektum típusa azConvertibleCar, de DescribeCar nem éri el az osztályban ConvertibleCar definiált verziótShowDetails, mert a metódus a módosítóval new van deklarálva, nem a override módosítóval. Ennek eredményeként egy ConvertibleCar objektum ugyanazzal a leírással jelenik meg, mint egy Car objektum. Ellentételezi az eredményeket az car3objektumnak Minivan számító objektummal. Ebben az esetben az ShowDetails osztályban Minivan deklarált metódus felülírja az ShowDetails osztályban Car deklarált metódust, és a megjelenő leírás egy kisbuszt ír le.

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

TestCars2 létrehoz egy listát a típussal Carrendelkező objektumokról. Az objektumok értékeit a rendszer a , ConvertibleCarés Minivan az Carosztályokból példányosítva hozza létre. DescribeCar a lista minden elemére meghívja. Az alábbi kód a definíciót TestCars2mutatja.

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

A következő kimenet jelenik meg. Figyelje meg, hogy ugyanaz, mint a kimenet, amelyet TestCars1a . Az ShowDetails osztály metódusának meghívása ConvertibleCar nem történik meg, függetlenül attól, hogy az objektum ConvertibleCartípusa az , mint az TestCars1, vagy Cara .TestCars2 Ezzel szemben car3 mindkét esetben meghívja a ShowDetails metódust az Minivan osztályból, legyen szó típusról Minivan vagy típusról Car.

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

Metódusok TestCars3 és TestCars4 a példa befejezése. Ezek a metódusok közvetlenül hívhatók ShowDetails meg, először a típusnak ConvertibleCar deklarált objektumokból, Minivan majd aTestCars3 típusnak () deklarált CarTestCars4objektumokból. A következő kód határozza meg ezt a két metódust.

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

A metódusok a következő kimenetet állítják elő, amely megfelel a jelen témakör első példájából származó eredményeknek.

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

Az alábbi kód a teljes projektet és annak kimenetét mutatja.

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

Lásd még