Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
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ököl BaseClass
-től.
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
egyBaseClass
típus, és értékeBaseClass
típusú.dc
egyDerivedClass
típus, és értékeDerivedClass
típusú.bcdc
egyBaseClass
típus, és értékeDerivedClass
típusú. Erre a változóra kell figyelni.
Mivel bc
és bcdc
az BaseClass
típusba tartoznak, csak közvetlenül férhetnek hozzá a Method1
-hoz, kivéve, ha típuskonverziót használ. A dc
változó hozzáfér mind a Method1
-hoz, mind a Method2
-hoz. 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 módszer szignatúrája megegyezik a Method2
módszer szignatúrájával a DerivedClass
-ben.
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
metódus a DerivedClass
elrejti a Method2
metódust a 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 elnyomásához adja hozzá a new
módosítót a Method2
fájlbeli DerivedClass
definícióhoz, ahogy az a következő kódban látható. 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. A(z) new
használatával azt állítja, hogy tisztában van azzal, hogy az általa módosított tag elrejt egy az alaposztályból örökölt 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ó hozzáadható a public
elé vagy mögé.
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
Adja hozzá a virtual
módosítót a(z) Method1
definícióhoz BaseClass
. A virtual
módosító hozzáadható a public
elé vagy mögé.
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
Futtassa újra 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 override
módosító használata lehetővé teszi bcdc
számára, hogy hozzáférjen a Method1
által definiált DerivedClass
metódushoz. Á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 úgy éri el, hogy a override
-t használja az alaposztály-metódus kibővítéséhez.
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 ConvertibleCar
Minivan
. 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ót arra használják, hogy meghatározzák a ShowDetails
-t a ConvertibleCar
osztályban. A override
módosítót arra használják, hogy meghatározzák a ShowDetails
-t a Minivan
osztályban.
// 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 teszteli, hogy melyik verziót hívják meg a ShowDetails
kapcsán. 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 a car2
eredményeit, amelyek valószínűleg nem azt mutatják, amire számított. Az objektum típusa azConvertibleCar
, de DescribeCar
nem éri el az osztályban ShowDetails
definiált verziótConvertibleCar
, 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. Hasonlítsa össze az eredményeket a car3
, amely egy Minivan
objektum. 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 az Car
, ConvertibleCar
és Minivan
osztályokból példányosítják. Minden listaelemre meghívódik a DescribeCar
. 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 TestCars1
által megjelenített kimenet. Az ShowDetails
osztály ConvertibleCar
metódusa nem hívódik meg, függetlenül attól, hogy az objektum típusa ConvertibleCar
, mint az TestCars1
, vagy Car
, mint az 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
teljesítik a példát. Ezek a metódusok közvetlenül hívják meg ShowDetails
, először a típusnak ConvertibleCar
deklarált Minivan
objektumokból, majd a TestCars3
típusnak deklarált Car
objektumokból TestCars4
. 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.");
}
}
}