C#에서 파생 클래스의 메서드는 기본 클래스의 메서드와 동일한 이름을 가질 수 있습니다.
new 키워드와 재정의 키워드를 사용하여 메서드의 상호 작용 방식을 지정할 수 있습니다.
override
한정자는 기본 클래스 메서드virtual
한 new
정자는 액세스 가능한 기본 클래스 메서드를 숨깁니다. 차이점은 이 항목의 예제에 설명되어 있습니다.
콘솔 애플리케이션에서 다음 두 클래스를 선언합니다BaseClass
. DerivedClass
DerivedClass
에서 상속됩니다 BaseClass
.
class BaseClass
{
public void Method1()
{
Console.WriteLine("Base - Method1");
}
}
class DerivedClass : BaseClass
{
public void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
메서드에서 Main
메서드에 bc
, dc
, 및 bcdc
변수를 선언하십시오.
bc
가 형식BaseClass
이고 해당 값은 형식BaseClass
입니다.dc
가 형식DerivedClass
이고 해당 값은 형식DerivedClass
입니다.bcdc
가 형식BaseClass
이고 해당 값은 형식DerivedClass
입니다. 이 변수는 주의해야 할 변수입니다.
bc
및 bcdc
은 BaseClass
유형이므로, 캐스팅을 사용하지 않으면 Method1
에 직접 액세스할 수 없습니다. 변수 dc
는 둘 다 Method1
에 액세스할 수 있습니다.Method2
이러한 관계는 다음 코드에 나와 있습니다.
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
}
다음으로 다음 Method2
메서드를 .에 추가합니다 BaseClass
. 이 메서드의 서명은 Method2
의 DerivedClass
메서드 서명과 일치합니다.
public void Method2()
{
Console.WriteLine("Base - Method2");
}
이제 BaseClass
에 Method2
메서드가 있기 때문에 아래 코드에 표시된 것처럼 BaseClass
및 bc
변수에 대해 bcdc
두 번째 호출 문을 추가할 수 있습니다.
bc.Method1();
bc.Method2();
dc.Method1();
dc.Method2();
bcdc.Method1();
bcdc.Method2();
프로젝트를 빌드할 때, Method2
에 BaseClass
메서드를 추가하면 경고가 발생한다. 경고는 Method2
의 DerivedClass
메서드가 Method2
에서 BaseClass
메서드를 숨긴다고 합니다.
new
정의에서 Method2
키워드를 사용하려는 경우에는 해당 결과를 발생시키기 위해 그렇게 하도록 권장됩니다. 또는 경고를 해결하기 위해 메서드 중 Method2
하나의 이름을 바꿀 수 있지만 항상 실용적인 것은 아닙니다.
추가 new
하기 전에 프로그램을 실행하여 추가 호출 문으로 생성된 출력을 확인합니다. 다음 결과가 표시됩니다.
// Output:
// Base - Method1
// Base - Method2
// Base - Method1
// Derived - Method2
// Base - Method1
// Base - Method2
키워드는 new
해당 출력을 생성하는 관계를 유지하지만 경고를 표시하지 않습니다. 형식 BaseClass
을 가진 변수는 계속해서 BaseClass
의 멤버에 액세스하고, 형식 DerivedClass
인 변수는 계속 먼저 DerivedClass
의 멤버에 액세스하며, 그 다음으로 BaseClass
에서 상속된 멤버를 고려합니다.
다음 코드와 같이 new
에서 Method2
의 정의에 DerivedClass
수정자를 추가하여 경고를 억제하십시오. 수식어는 public
앞 또는 뒤에 추가할 수 있습니다.
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
프로그램을 다시 실행하여 출력이 변경되지 않은지 확인합니다. 또한 경고가 더 이상 표시되지 않는지 확인합니다. 이를 사용하여 new
수정하는 멤버가 기본 클래스에서 상속된 멤버를 숨기는 것을 알고 있음을 어설션합니다. 상속을 통해 숨기는 이름에 대한 자세한 내용은 새 한정자를 참조하세요.
이 동작을 사용 override
효과와 대조하려면 다음 메서드를 추가합니다 DerivedClass
.
override
수식어는 public
앞이나 뒤에 추가할 수 있습니다.
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
virtual
에서 Method1
의 정의에 BaseClass
한정자를 추가합니다.
virtual
수식어는 public
앞이나 뒤에 추가할 수 있습니다.
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
프로젝트를 다시 실행합니다. 특히 다음 출력의 마지막 두 줄을 확인합니다.
// Output:
// Base - Method1
// Base - Method2
// Derived - Method1
// Derived - Method2
// Derived - Method1
// Base - Method2
override
한정자를 사용하면 bcdc
에 정의된 Method1
메서드에 DerivedClass
이(가) 액세스할 수 있습니다. 일반적으로 상속 계층에서 원하는 동작입니다. 파생 클래스에서 만든 값이 있는 개체가 파생 클래스에 정의된 메서드를 사용하려고 합니다.
override
를 사용하여 기본 클래스 메서드를 확장함으로써 해당 동작을 달성할 수 있습니다.
다음 코드에는 전체 예제가 포함되어 있습니다.
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");
}
}
}
다음 예제에서는 다른 컨텍스트에서 유사한 동작을 보여 줍니다. 이 예제에서는 세 가지 클래스, 즉 명명된 기본 클래스와 이 Car
클래스에서 파생된 두 개의 클래스를 ConvertibleCar
정의합니다 Minivan
. 기본 클래스에는 메서드가 포함되어 있습니다 DescribeCar
. 메서드는 자동차에 대한 기본 설명을 표시한 다음 추가 정보를 제공하기 위해 호출 ShowDetails
합니다. 세 클래스는 각각 메서드를 ShowDetails
정의합니다.
new
수정자는 클래스 내에서 ShowDetails
정의하려는 ConvertibleCar
데 사용합니다.
override
수정자는 클래스 내에서 ShowDetails
정의하려는 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.");
}
}
예제는 어떤 버전의 ShowDetails
이(가) 호출되는지를 테스트합니다. 다음 메서드는 TestCars1
각 클래스의 인스턴스를 선언한 다음 각 인스턴스를 호출 DescribeCar
합니다.
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
는 다음 출력을 생성합니다. 특히 car2
의 결과를 주의 깊게 보십시오. 아마도 예상과 다른 결과일 것입니다. 개체의 유형은 ConvertibleCar
이지만, DescribeCar
은 ShowDetails
클래스에 정의된 ConvertibleCar
의 버전에 접근하지 않습니다. 이는 해당 메서드가 new
한정자가 아닌 override
한정자를 사용하여 선언되었기 때문입니다. 결과적으로 ConvertibleCar
개체는 Car
개체와 동일한 설명을 표시합니다.
car3
결과를 대조하세요. 이것은 Minivan
객체입니다. 이 경우 ShowDetails
클래스의 Minivan
메서드는 ShowDetails
클래스의 Car
메서드를 재정의하며, 표시되는 설명은 미니밴에 관한 것입니다.
// TestCars1
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Carries seven people.
// ----------
TestCars2
는 형식 Car
이 있는 개체 목록을 만듭니다. 개체의 값은 Car
, ConvertibleCar
, 및 Minivan
클래스에서 인스턴스화됩니다.
DescribeCar
는 목록의 각 요소에서 호출됩니다. 다음 코드는 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("----------");
}
}
다음 출력이 표시됩니다.
TestCars1
에 의해 표시되는 결과와 동일함을 유의하십시오.
ShowDetails
클래스의 메서드는 개체ConvertibleCar
의 ConvertibleCar
형식에 관계 없이 호출 되지 않습니다.TestCars1
Car
TestCars2
반대로, 두 경우 모두 car3
는 ShowDetails
클래스의 Minivan
메서드를 호출하며, 이는 형식이 Minivan
이든 Car
이든 같습니다.
// TestCars2
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Carries seven people.
// ----------
메서드 TestCars3
를 사용하고 TestCars4
예제를 완료합니다. 이러한 메서드는 우선 형식 ShowDetails
및 ConvertibleCar
(Minivan
)으로 선언된 개체에서 TestCars3
을 직접 호출하고, 그런 다음 형식 Car
(TestCars4
)으로 선언된 개체에서 호출합니다. 다음 코드는 이러한 두 가지 메서드를 정의합니다.
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();
}
메서드는 이 항목의 첫 번째 예제의 결과에 해당하는 다음 출력을 생성합니다.
// TestCars3
// ----------
// A roof that opens up.
// Carries seven people.
// TestCars4
// ----------
// Standard transportation.
// Carries seven people.
다음 코드는 전체 프로젝트 및 해당 출력을 보여 있습니다.
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.");
}
}
}
참고하십시오
.NET