베이스 클래스가 업그레이드된 경우에만 new 한정자를 사용하라
비가상 메서드는 정적으로 바인딩된다. 이는 런타임에 파생 클래스에서 새롭게 정의하고 있는 메서드를 호출한다.
가상 메서드는 동적으로 바인딩된다. 이는 런타임에 객체 타입이 무엇이냐에 따라 파생 클래스에서 새롭게 정의하고 있는 메서드를 호출한다.
new 한정자는 비가상 메서드를 가상 메서드로 바꾸는 것이 아니라 명명 범위(naming scope) 내에 새로운 메서드를 추가하는 역할을 한다.
예시 소스부터 보자
public class MyClass
{
public void MagicMethod(){...}
}
public class MyOtherClass : MyClass
{
publie new void MagicMethod(){...}
}
object c = MakeObject();
MyClass cl = c as MyClass;
cl.MagicMethod();
MyOherClass cl2 = c as MyOtherClass;
cl2.MagicMethod();
두 메서드의 호출 결과는 각각 다르다. 이와 같은 코드를 보는 개발자들은 혼란스러울 뿐이다. 왜냐하면 동일한 객체를 이용하여 동일한 메서드를 호출했지만 결과는 다르기 때문이다. 내가 제일 중요시 여기는 협업하는 코딩에서는 쥐약인 형태이다.
사실 이런 한정자는 C#에서 왜 제공하는지는 잘 모르지만 덕분에 개발의 자유도는 높아진 것 같다.
사용해야 하는 상황이 책에 나와있으니 예시를 올리겠다.
상황 : 헬스 쟁이 개발자는 Widget회사에서 제공하는 BaseWidget Class를 상속받아 휘황찬란한 Widget을 만들고 있었다. 뿐만 아니라 협업하는 개발자 A, B, C.... Z들도 쓰고 있었다.
public class MyWidget : BaseWidget
{
public void NormalizeValues(){...}
}
그런데 어느 날 Widget회사에서 새로운 버전을 출시했다고 한다.
새로운 기능을 기대하고 있던 헬스 쟁이 개발자는 당장 구매하여 이전 BaseWidget Class를 갈아치웠다.
public class MyWidget : newBaseWidget
{
public void NormalizeValues(){...}///빨간줄
}
큰일이다 자세히 보니
public class newBaseWidget
{
public void NormalizeValues(){...}
}
newBaseWidget에 같은 이름의 함수가 생겨난 것이다...
여기서 2가지 방법이 있다.
방법 1 (소요시간 약 일주일)
NormalizeValues 함수 명을 바꾼다.
그리고 NormalizeValues함수를 사용하는 모든 코드를 수정한다.
public class MyWidget : newBaseWidget
{
public void NormalizeAllValues()
{
base.NormalizeValues();
}
}
방법 2 (소요시간 약 10분)
new 한정자를 써서 탈출한다.
public class MyWidget : newBaseWidget
{
public new void NormalizeValues()
{
base.NormalizeValues();
}
}
자 문제는 해결했다. 하지만 장기적인 대안으로 봤을 때는 방법 1이 올바른 방법이다.
간혹 누군가가 newBaseWidget이라는 Class를 다루면 조금씩 꼬이기 시작하기 때문이다.
당장 내가 3달 안에 퇴사를 한다면 방법 2가 좋을 수도 있다.
하지만 뼈를 묻는다면 무조건 방법 1이 좋다!!
'Program > Effective C#' 카테고리의 다른 글
Effective C# ITEM14 (0) | 2020.10.28 |
---|---|
Effective C# ITEM13 (0) | 2020.10.28 |
Effective C# ITEM 12 (0) | 2020.10.26 |
Effective C# ITEM11 (0) | 2020.10.25 |
Effective C# ITEM9 (0) | 2020.10.21 |