방프리
23.01.24 Chapter2. API 설계 (Item 11) 본문
Item 11 : API에는 변환 연산자를 작성하지 말라
처음 객체지향을 배울 때 상속이라는 개념을 배운다. 이를 토대로 C#에서는 모든 데이터 타입은 System.Object 타입을
상속받고 있다. 보통 상속이라는 개념을 설명할 때에는 도형을 자주 빗대어 설명한다.
public class Circle : Shape
{
private Point center;
private double radius;
public Circle() :
this(new Point(), 0)
{
}
public Circle(Point c, double r)
{
center = c;
radius = r;
}
public override void Draw()
{
//...
}
static public implicit operator Ellipse(Circle c)
{
return new Ellipse(c.center, c.center, c.radius, c.radius);
}
}
모든 원은 도형이 될 수 있으며 모든 타원은 operator Ellipse 메서드를 통해 암묵적 변환이 가능하도록 정의하였다.
해당 메서드를 통해 다음의 함수는 정상적으로 동작할 수 있게 되었다.
public static double ComputeArea(Ellipse e) => e.R1 * e.R2 * Math.PI;
Circle c1 = new Circle(new Point(3.0, 0), 5.0f);
ComputeArea(c1);
하지만 다음의 함수에서는 정상적으로 동작하지 않는다.
public static void Flatten(Ellipse e)
{
e.R1 /= 2;
e.R2 *= 2;
}
Circle c = new Circle(new Point(3.0, 0), 5.0f);
Flatten(c);
왜일까? 두 함수의 차이를 잘 생각해보면 될 것 같다. 위의 함수는 객체의 속성값을 통해 새로운 결과값을 반환한다.
하지만 두 번째 함수는 객체의 속성값을 변경한다.
Circle 클래스는 operator Ellipse 함수를 잘 보면 객체를 그대로 넘기는 것이 아닌 새로 생성 후 객체를 넘기고 있다.
이러면 객체 원본이 아닌 임시객체를 함수 인자로 넘기게 되기 때문이다. 그렇다면 해결방법은 없는걸까?
Circle c = new Circle(new Point(3.0, 0), 5.0f);
Flatten(c);
// 원 관련 처리
// ...
// 타원으로 변환
Ellipse e = new Ellipse(c);
Flatten(e);
아예 타원 객체를 생성 후 넘기는 것이다. 이렇게 되면 임시 객체를 생성하지 않고 Flatten 함수도 정상적으로 동작한다.
암묵적 변환은 정말 편리한 기능이다. 하지만 명시적이지 않았을 때 오류가 나게되면 찾기 어렵다는 점
그리고 이와 같이 사용할 수 있는 범위가 제한이 있다는 점을 인지하고 있는 상태에서 사용해야한다.
'C# > More Effective C#' 카테고리의 다른 글
23.01.30 Chapter2. API 설계 (Item 13) (0) | 2023.01.30 |
---|---|
23.01.25 Chapter2. API 설계 (Item 12) (0) | 2023.01.26 |
23.01.23 Chapter1. 데이터 타입 (Item 10) (0) | 2023.01.23 |
22.05.09 Chapter1. 데이터 타입 (Item 9) (0) | 2022.05.08 |
22.05.08 Chapter1. 데이터 타입 (Item 8) (0) | 2022.05.07 |
Comments