C# 언어는 서로 다른 라이브러리의 기본 클래스와 파생 클래스 간의 버전 관리를 발전시키고 이전 버전과의 호환성을 유지할 수 있도록 설계되었습니다. 예를 들어 파생 클래스의 멤버와 이름이 같은 기본 클래스 에 새 멤버를 도입하는 것은 C#에서 완전히 지원되며 예기치 않은 동작으로 이어지지 않습니다. 또한 클래스는 메서드가 상속된 메서드를 재정의할 것인지 또는 메서드가 비슷한 이름의 상속된 메서드를 숨기는 새 메서드인지 여부를 명시적으로 명시해야 합니다.
C#에서 파생 클래스는 기본 클래스 메서드와 이름이 같은 메서드를 포함할 수 있습니다.
파생 클래스의 메서드 앞에 새 또는 오버라이드 키워드가 없으면 컴파일러가 경고를 발생시키고 메서드는
new
키워드가 있는 것처럼 동작합니다.파생 클래스의 메서드 앞에
new
키워드가 있으면 메서드는 기본 클래스의 메서드와 독립적인 것으로 정의됩니다.파생 클래스의 메서드 앞에
override
키워드가 있으면 파생 클래스의 개체가 기본 클래스 메서드 대신 해당 메서드를 호출합니다.파생 클래스의
override
메서드에 키워드를 적용하려면 기본 클래스 메서드를 가상으로 정의해야 합니다.키워드를 사용하여 파생 클래스 내에서 기본 클래스 메서드를
base
호출할 수 있습니다.override
및virtual
new
키워드를 속성, 인덱서 및 이벤트에 적용할 수도 있습니다.
기본적으로 C# 메서드는 가상이 아닙니다. 메서드가 가상으로 선언된 경우 메서드를 상속하는 모든 클래스가 자체 버전을 구현할 수 있습니다. 메서드를 가상 virtual
으로 만들기 위해 한정자는 기본 클래스의 메서드 선언에 사용됩니다. 그런 다음 파생 클래스는 override
키워드를 사용하여 기본 가상 메서드를 재정의하거나 new
키워드를 사용하여 기본 클래스에서 가상 메서드를 숨길 수 있습니다.
override
키워드와 new
키워드를 모두 지정하지 않으면 컴파일러가 경고를 표시하고 파생 클래스의 메서드는 기본 클래스의 메서드를 숨깁니다.
실제로 이를 보여 주려면 A사에서 프로그램에서 사용하는 클래스 GraphicsClass
를 만들었다고 가정합니다. 다음은 다음과 같습니다.GraphicsClass
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
}
회사에서 이 클래스를 사용하며, 이 클래스를 사용하여 사용자 고유의 클래스를 파생시키고 새 메서드를 추가합니다.
class YourDerivedGraphicsClass : GraphicsClass
{
public void DrawRectangle() { }
}
A사에서 다음 코드와 유사한 새 버전의 GraphicsClass
애플리케이션을 릴리스할 때까지 애플리케이션은 문제 없이 사용됩니다.
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
public virtual void DrawRectangle() { }
}
이제 새 버전 GraphicsClass
에는 이름이 DrawRectangle
지정된 메서드가 포함되어 있습니다. 처음에는 아무 것도 발생하지 않습니다. 새 버전은 이전 버전과 여전히 이진 호환됩니다. 배포한 모든 소프트웨어는 새 클래스가 해당 컴퓨터 시스템에 설치되어 있더라도 계속 작동합니다. 파생 클래스에서 메서드 DrawRectangle
에 대한 기존 호출은 계속해서 사용자의 버전을 참조합니다.
그러나 새 버전을 GraphicsClass
사용하여 애플리케이션을 다시 컴파일하는 즉시 컴파일러 CS0108에서 경고가 표시됩니다. 이 경고는 애플리케이션에서 DrawRectangle
메서드가 어떻게 동작해야 하는지를 검토해야 한다는 것을 알려줍니다.
메서드가 새 기본 클래스 메서드를 재정의하도록 하려면 다음 키워드를 override
사용합니다.
class YourDerivedGraphicsClass : GraphicsClass
{
public override void DrawRectangle() { }
}
override
키워드는 모든 YourDerivedGraphicsClass
로부터 파생된 개체가 DrawRectangle
의 파생 클래스 버전을 사용하도록 합니다. 파생된 개체는 YourDerivedGraphicsClass
기본 키워드를 사용하여 기본 클래스 버전 DrawRectangle
에 계속 액세스할 수 있습니다.
base.DrawRectangle();
메서드가 새 기본 클래스 메서드를 재정의하지 않으려면 다음 고려 사항이 적용됩니다. 두 메서드 간의 혼동을 방지하기 위해 메서드의 이름을 바꿀 수 있습니다. 이는 시간이 많이 걸리고 오류가 발생하기 쉬울 수 있으며 경우에 따라 실용적이지 않을 수 있습니다. 그러나 프로젝트가 비교적 작은 경우 Visual Studio의 리팩터링 옵션을 사용하여 메서드의 이름을 바꿀 수 있습니다. 자세한 내용은 클래스 및 형식 리팩터링(클래스 디자이너)을 참조하세요.
또는 파생 클래스 정의에서 키워드 new
를 사용하여 경고를 방지할 수 있습니다.
class YourDerivedGraphicsClass : GraphicsClass
{
public new void DrawRectangle() { }
}
키워드를 new
사용하면 정의가 기본 클래스에 포함된 정의를 숨긴다는 것을 컴파일러에 알릴 수 있습니다. 이 옵션은 기본 동작입니다.
재정의 및 메서드 선택
클래스에 메서드 이름이 지정되면 C# 컴파일러는 이름이 같은 두 메서드와 전달된 매개 변수와 호환되는 매개 변수가 있는 경우와 같이 둘 이상의 메서드가 호출과 호환되는 경우 호출할 최상의 메서드를 선택합니다. 다음 메서드는 호환됩니다.
public class Derived : Base
{
public override void DoWork(int param) { }
public void DoWork(double param) { }
}
DoWork
이 Derived
의 인스턴스에서 호출될 때, C# 컴파일러는 먼저 호출이 Derived
에 원래 선언된 DoWork
버전과 호환되도록 시도할 것입니다. 재정의 메서드는 클래스에 선언된 것으로 간주되지 않으며 기본 클래스에 선언된 메서드의 새 구현입니다. C# 컴파일러가 원래 메서드에 대한 메서드 호출과 일치할 수 없는 경우에만 재정의된 메서드에 대한 Derived
호출을 동일한 이름과 호환되는 매개 변수와 일치시키려고 시도합니다. 다음은 그 예입니다.
int val = 5;
Derived d = new();
d.DoWork(val); // Calls DoWork(double).
변수 val
를 암시적으로 double로 변환할 수 있으므로 C# 컴파일러는 DoWork(double)
DoWork(int)
. 이를 방지하는 방법에는 두 가지가 있습니다. 먼저 가상 메서드와 이름이 같은 새 메서드를 선언하지 않습니다. 둘째, 인스턴스 Derived
를 캐스팅하여 기본 클래스 메서드 목록을 검색하도록 하여 가상 메서드를 호출하도록 C# 컴파일러에 지시할 Base
수 있습니다. 메서드는 가상이므로 on Derived
의 DoWork(int)
구현이 호출됩니다. 다음은 그 예입니다.
((Base)d).DoWork(val); // Calls DoWork(int) on Derived.
new
및 override
예제에 대한 자세한 내용은 재정의 및 새 키워드를 사용해야 할 때 알기를 참조하십시오.
참고하십시오
.NET