개발/C#

[Effective C#] new 한정자 사용

huiyu 2021. 1. 29. 06:00

Effective C# 아이템 10 : 베이스 클래스가 업그레이드된 경우에만 new 한정자를 사용하라.

public class MyClass
{
  public void MagicMethod()
  {
    Console.WriteLine("MyClass");
  }
}

public class MyOtherClass : MyClass
{
  public new void MagicMethod()
  {
    Console.WriteLine("MyOtherClass");
  }
}

 베이스 클래스에서 virtual로 선언한지 않은 멤버를 상속받은 클래스에서 new 한정자를 통해 재정의할 수 있다. 재정의를 통해 구현이 가능하지만 사용자에게 모호함을 줄 수 있다.

object c = MakeObject();

MyClass cl = c as MyClass;
cl.MagicMethod();

MyOtherClass cl2 = c as MyOtherClass;
cl2.MagicMethod();

 위 예제는 개발자는 두 메서드가 동일하다고 생각하게 되고 작업할 수 있다. cl1과 cl2 객체는 모두 동일한 객체에서 생성되었기 때문이다. 보통은 참조하는 값이 변경된다고 동작이 바뀔 것이라고 생각하지 않기 때문이다. 이는 일관성이 없는 코드를 제공하여 개발자에게 혼란을 줄 수 있다.

 비가상 메서드는 정적으로 바인딩되어 MyClass.MagicMethod()를 호출하는 코드는 정확히 이 메서드를 호출한다. 런타임에 파생 클래스에서 새롭게 정의하고 있는 메서드가 있는지 찾지 않는다. 그러나 가상메서드(virtual)는 동적으로 바인딩되므로 런타임에 객체의 타입이 무엇이냐에 따라 그에 부합하는 메서드를 호출한다. 
-> new 한정자는 비가상 메서드를 가상 메서드로 만드는 것이 아니라 naming scope 내에 새로운 메서드를 추가하는 역할을 한다.(참고)

 그렇다면 부모 클래스의 함수를 모두 virtual(가상) 함수로 선언하면 해결될까?
이 또한 라이브러리 설계시 고민해야 된다. 가상 메서드로 선언된 함수는 파생 클래스에서 이 가상 메서드의 구현부를 변경할 수 있다는 것을 의미한다. 베이스 클래스의 동작에도 영향을 주는 변경이 있을 수 있으므로 신중해야 하며, 이러한 구현은 다형성이 필요한 측면에서 제공되어져야 한다.

new가 고려되야 할 경우
-> 베이스 클래스에서 이미 사용하고 있는 메서드를 재정의하여 새로운 베이스 클래스를 만들어야 하는 경우에 사용.
new 한정자를 사용하면 기존 메서드명을 그대로 사용할 수 있기 때문! 그러나 장기적으로 봤을 때 이름은 같지만 서로 다르게 동작하는 메서드가 여러 개 존재하게 되어 이는 신중하게 고민해야 된다.

 

** 이번 아이템의 경우엔 new와 override 키워드 사용에 대해 생각해보게 됐다. 보통은 new와 override는 편리함때문에 많이 사용하게 되는데, 꼭 필요한 경우가 아니라 무분별하게 사용하면 함수 사용에 모호함이 생길 수 있고 이로 인해 문제도 생길 수 있을 거 같다. 사용전에 꼭 필요여부와 문제 상황에 대해 고민해보자.

728x90
반응형