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 BaseClass
DerivedClass
. 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ípusBaseClass
.dc
típusúDerivedClass
, értéke pedig típusDerivedClass
.bcdc
típusúBaseClass
, értéke pedig típusDerivedClass
. 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 Method2
a . 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 DerivedClass
aláí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 BaseClass
bc
, és bcdc
az 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 new
elő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 BaseClass
tagokat.
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 Method2
DerivedClass
. A módosító a következő előtt vagy után public
adható 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 new
azt á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 override
hatá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 public
adható hozzá.
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
Adja hozzá a virtual
módosítót a következő definícióhozBaseClass
Method1
: A virtual
módosító a következő előtt vagy után public
adható 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 DerivedClass
metó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 Minivan
ConvertibleCar
. 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 TestCars1
az 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 car3
objektumnak 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 Car
rendelkező objektumokról. Az objektumok értékeit a rendszer a , ConvertibleCar
és Minivan
az Car
osztá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 TestCars2
mutatja.
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 TestCars1
a . Az ShowDetails
osztály metódusának meghívása ConvertibleCar
nem történik meg, függetlenül attól, hogy az objektum ConvertibleCar
típusa az , mint az TestCars1
, vagy Car
a .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 Car
TestCars4
objektumokbó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.");
}
}
}