Weten wanneer u onderdrukking en nieuwe trefwoorden moet gebruiken (C#-programmeerhandleiding)

In C# kan een methode in een afgeleide klasse dezelfde naam hebben als een methode in de basisklasse. U kunt opgeven hoe de methoden communiceren met behulp van de nieuwe trefwoorden en trefwoorden overschrijven . De override modifier breidt de basisklassemethode virtual uit en de new modifier verbergt een toegankelijke basisklassemethode. Het verschil wordt geïllustreerd in de voorbeelden in dit onderwerp.

Declareer in een consoletoepassing de volgende twee klassen en BaseClassDerivedClass. DerivedClass neemt over van BaseClass.

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

Declareer variabelen bcin de Main methode , dcen bcdc.

  • bc is van het type BaseClassen de waarde is van het type BaseClass.

  • dc is van het type DerivedClassen de waarde is van het type DerivedClass.

  • bcdc is van het type BaseClassen de waarde is van het type DerivedClass. Dit is de variabele waar u aandacht aan moet besteden.

Omdat bc ze bcdc type hebben BaseClass, hebben ze alleen rechtstreeks toegang Method1, tenzij je cast gebruikt. Variabele dc heeft toegang tot zowel Method2Method1 als . Deze relaties worden weergegeven in de volgende 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  
}  

Voeg vervolgens de volgende Method2 methode toe aan BaseClass. De handtekening van deze methode komt overeen met de handtekening van de Method2 methode in DerivedClass.

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

Omdat BaseClass er nu een Method2 methode is, kan er een tweede aanroepinstructie worden toegevoegd voor BaseClass variabelen bc en bcdc, zoals wordt weergegeven in de volgende code.

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

Wanneer u het project bouwt, ziet u dat de toevoeging van de Method2 methode een BaseClass waarschuwing veroorzaakt. De waarschuwing geeft aan dat de Method2 methode in DerivedClass de Method2 methode wordt verborgen in BaseClass. U wordt aangeraden het new trefwoord in de Method2 definitie te gebruiken als u dat resultaat wilt veroorzaken. U kunt ook de naam van een van de Method2 methoden wijzigen om de waarschuwing op te lossen, maar dat is niet altijd praktisch.

Voordat u het toevoegt new, voert u het programma uit om de uitvoer te zien die is geproduceerd door de aanvullende aanroepende instructies. De volgende resultaten worden weergegeven.

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

Het new trefwoord behoudt de relaties die die uitvoer produceren, maar onderdrukt de waarschuwing. De variabelen met het type BaseClass blijven toegang krijgen tot de leden van BaseClassen de variabele die het type DerivedClass heeft, blijft eerst toegang krijgen tot leden DerivedClass en vervolgens om leden te overwegen die zijn overgenomen van BaseClass.

Als u de waarschuwing wilt onderdrukken, voegt u de new wijziging toe aan de definitie van Method2 in DerivedClass, zoals wordt weergegeven in de volgende code. De wijzigingsfunctie kan vóór of na publicworden toegevoegd.

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

Voer het programma opnieuw uit om te controleren of de uitvoer niet is gewijzigd. Controleer ook of de waarschuwing niet meer wordt weergegeven. Door te gebruiken new, bevestigt u dat u weet dat het lid dat wordt gewijzigd, een lid verbergt dat is overgenomen van de basisklasse. Zie de nieuwe wijzigingsfunctie voor meer informatie over het verbergen van namen via overname.

Als u dit gedrag wilt contrasteren met de effecten van het gebruik override, voegt u de volgende methode toe aan DerivedClass. De override wijzigingsfunctie kan vóór of na publicworden toegevoegd.

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

Voeg de virtual wijzigingsfunctie toe aan de definitie van Method1 in BaseClass. De virtual wijzigingsfunctie kan vóór of na publicworden toegevoegd.

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

Voer het project opnieuw uit. Let vooral op de laatste twee regels van de volgende uitvoer.

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

Het gebruik van de override modifier maakt bcdc het mogelijk om toegang te krijgen tot de Method1 methode die is gedefinieerd in DerivedClass. Dit is doorgaans het gewenste gedrag in overnamehiërarchieën. U wilt dat objecten met waarden die zijn gemaakt op basis van de afgeleide klasse, gebruikmaken van de methoden die zijn gedefinieerd in de afgeleide klasse. U bereikt dit gedrag door de override basisklassemethode uit te breiden.

De volgende code bevat het volledige voorbeeld.

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

In het volgende voorbeeld ziet u een vergelijkbaar gedrag in een andere context. In het voorbeeld worden drie klassen gedefinieerd: een basisklasse met de naam Car en twee klassen die ermee zijn afgeleid, ConvertibleCar en Minivan. De basisklasse bevat een DescribeCar methode. De methode geeft een basisbeschrijving van een auto weer en roept ShowDetails vervolgens aan om aanvullende informatie op te geven. Elk van de drie klassen definieert een ShowDetails methode. De new wijzigingsfunctie wordt gebruikt om in de ConvertibleCar klasse te definiërenShowDetails. De override wijzigingsfunctie wordt gebruikt om in de Minivan klasse te definiërenShowDetails.

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

In het voorbeeld wordt getest welke versie wordt ShowDetails aangeroepen. Met de volgende methode TestCars1declareert u een exemplaar van elke klasse en roept DescribeCar u vervolgens elk exemplaar aan.

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 produceert de volgende uitvoer. Let vooral op de resultaten, car2die waarschijnlijk niet zijn wat u had verwacht. Het type van het object is ConvertibleCar, maar DescribeCar heeft geen toegang tot de versie van ShowDetails die versie die in de ConvertibleCar klasse is gedefinieerd, omdat die methode wordt gedeclareerd met de new modifier, niet de override modifier. Als gevolg hiervan geeft een ConvertibleCar object dezelfde beschrijving weer als een Car object. Vergelijk de resultaten voor car3, een Minivan object. In dit geval overschrijft de ShowDetails methode die in de Minivan klasse wordt gedeclareerd de ShowDetails methode die in de Car klasse wordt gedeclareerd en de beschrijving die wordt weergegeven een 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 maakt een lijst met objecten met het type Car. De waarden van de objecten worden geïnstantieerd vanuit de Car, ConvertibleCaren Minivan klassen. DescribeCar wordt aangeroepen op elk element van de lijst. De volgende code toont de definitie van 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("----------");  
    }  
}  

De volgende uitvoer wordt weergegeven. U ziet dat dit hetzelfde is als de uitvoer die wordt weergegeven door TestCars1. De ShowDetails methode van de ConvertibleCar klasse wordt niet aangeroepen, ongeacht of het type van het object , ConvertibleCarzoals in TestCars1, of Car, zoals in TestCars2. Daarentegen car3 wordt de ShowDetails methode in beide gevallen aangeroepen vanuit de Minivan klasse, ongeacht of deze type Minivan of type Carheeft.

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

Methoden TestCars3 en TestCars4 voltooi het voorbeeld. Deze methoden roepen ShowDetails rechtstreeks aan, eerst van objecten die zijn gedeclareerd om type ConvertibleCar en () te hebben en Minivan vervolgensTestCars3 van objecten die zijn gedeclareerd om het type Car (TestCars4) te hebben. De volgende code definieert deze twee methoden.

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

De methoden produceren de volgende uitvoer, die overeenkomt met de resultaten uit het eerste voorbeeld in dit onderwerp.

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

De volgende code toont het volledige project en de uitvoer ervan.

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

Zie ook