new 한정자
new 한정자 (C# Reference)
파생 클래스를 만들다 보면, 베이스 클래스가 이미 갖고 있던 맴버를 같은 이름으로 다시 선언하고 싶은 순간이 와요. 이때 new 키워드를 **선언 한정자(declaration modifier)**로 붙이면, 베이스 클래스가 제공하는 맴버를 명시적으로 숨길 수 있답니다. 상속받은 맴버를 숨기면, 파생 클래스 버전이 베이스 클래스 버전을 대체해요.
맴버를 숨길 수 있는 조건이 하나 있어요. 베이스 클래스 버전이 파생 클래스에서 보여야 한다는 거예요. private으로 표시된 맴버나, 경우에 따라 internal로 표시된 맴버는 파생 클래스에서는 보이지 않으니 숨길 수 없어요. 반대로 public이나 protected 맴버는 new 한정자 없이도 숨길 수 있지만, 그렇게 하면 컴파일러 경고가 발생해요. new로 명시적으로 숨기면 그 경고를 없앨 수 있답니다.
이 내용은 C#의 초기 버전부터 적용돼요.
new 키워드는 한정자 외에도 두 가지로 더 쓰여요. 형식의 인스턴스를 만들 때와, 제네릭 형식 제약 조건으로 쓰이죠.
본문
기본적인 사용법
상속받은 맴버를 숨기려면, 파생 클래스에서 같은 맴버 이름으로 선언하고 new 키워드로 한정하면 돼요. 예를 들면 이렇죠.
public class BaseC
{
public int x;
public void Invoke() { }
}
public class DerivedC : BaseC
{
new public void Invoke() { }
}
이 예시에서는 BaseC.Invoke가 DerivedC.Invoke에 숨겨져요. 필드 x는 같은 이름으로 숨겨진 게 아니기 때문에 영향을 받지 않아요.
어떤 형태로 숨겨질까
상속을 통한 이름 숨김은 크게 세 가지 형태로 나타나요.
- 클래스나 구조체에서 도입한 상수·필드·속성·형식은 일반적으로 그 이름을 공유하는 모든 베이스 클래스 맴버를 숨겨요. 다만 몇 가지 특별한 경우가 있어요. 예를 들어 이름이
N인 새 필드를 호출할 수 없는 형식으로 선언했는데, 베이스 형식이N을 메서드로 선언한 경우라면, 이 새 필드는 호출 구문에서 베이스 선언을 숨기지 못해요. 자세한 내용은 C# 언어 사양의 멤버 조회 섹션을 참고하세요. - 클래스나 구조체에서 도입한 메서드는 베이스 클래스에서 같은 이름을 가진 속성·필드·형식을 숨겨요. 또한 **같은 시그니처(signature)**를 가진 모든 베이스 클래스 메서드도 숨겨요.
- 클래스나 구조체에서 도입한 인덱서는 같은 시그니처를 가진 모든 베이스 클래스 인덱서를 숨겨요.
같은 맴버에 new와 override를 둘 다 쓰는 것은 오류예요. 두 한정자의 의미가 서로 배타적이거든요. new는 같은 이름의 새 맴버를 만들어 원래 맴버를 숨기고, override는 상속받은 맴버의 구현을 확장해요.
그리고 new 한정자를 썼는데 실제로 숨기는 상속 맴버가 없다면, 그 선언은 경고를 발생시켜요.
필드 이름 숨기기
베이스 클래스 BaseC와 파생 클래스 DerivedC가 같은 필드 이름 x를 사용해서 상속된 필드 값을 숨기는 예시예요. new 한정자 사용법과, 정규화된 이름(fully qualified name)으로 베이스 클래스의 숨겨진 맴버에 접근하는 방법을 모두 보여줘요.
public class BaseC
{
public static int x = 55;
public static int y = 22;
}
public class DerivedC : BaseC
{
// Hide field 'x'.
new public static int x = 100;
static void Main()
{
// Display the new value of x:
Console.WriteLine(x);
// Display the hidden value of x:
Console.WriteLine(BaseC.x);
// Display the unhidden member y:
Console.WriteLine(y);
}
}
/*
Output:
100
55
22
*/
중첩 형식 이름 숨기기
이번엔 중첩 클래스가 베이스 클래스에서 같은 이름을 가진 클래스를 숨기는 예시예요. new 한정자로 경고 메시지를 없애는 방법과, 정규화된 이름으로 숨겨진 클래스 맴버에 접근하는 방법을 보여줘요.
public class BaseC
{
public class NestedC
{
public int x = 200;
public int y;
}
}
public class DerivedC : BaseC
{
// Nested type hiding the base type members.
new public class NestedC
{
public int x = 100;
public int y;
public int z;
}
static void Main()
{
// Creating an object from the overlapping class:
NestedC c1 = new NestedC();
// Creating an object from the hidden class:
BaseC.NestedC c2 = new BaseC.NestedC();
Console.WriteLine(c1.x);
Console.WriteLine(c2.x);
}
}
/*
Output:
100
200
*/
만약 new 한정자를 지우면 프로그램은 여전히 컴파일되고 실행되지만, 다음과 같은 경고가 발생해요.
The keyword new is required on 'MyDerivedC.x' because it hides inherited member 'MyBaseC.x'.