다음 본문은 도서 이펙티브 C# (빌 와그너)에서 나오는 주제를 다룹니다.
상속된 클래스의 생성자는 꽤 주의해서 다루어야 한다.
2021.04.26 - [C# Study/C# 케이스 스터디] - C# 상속 클래스 부모의 생성자 호출 순서
상속 클래스가 인스턴스화 될 때 부모의 생성자가 먼저 호출된다.
그런데 부모 생성자 내에서 호출하는 함수가 가상 함수(virtual)로 지정되어있고,
이를 자식 클래스에서 오버라이딩한 경우를 생각해보자.
public class TestScript : MonoBehaviour
{
[Button]
public void Test()
{
var Temp = new B("test");
}
}
public class A
{
public A()
{
Debug.Log("A");
MyMethod();
}
public virtual void MyMethod()
{
Debug.Log("부모 클래스의 가상함수");
}
}
public class B : A
{
public B(string str)
{
Debug.Log($"B {str}");
}
public override void MyMethod()
{
Debug.Log("자식 클래스의 오버라이딩 함수");
}
}
먼저 부모 클래스의 생성자가 호출되고, 부모 생성자 내에서 가상 함수가 호출되며,
이 가상 함수는 자식이 오버라이딩했으니 오버라이딩된 함수가 호출된다.
이 시점에서 자식 클래스의 생성자가 완료되지 않았지만 자식클래스의 함수를 호출하였다.
생성자가 완료되기 전까지는 객체가 완전히 생성된 것이 아니다. 때문에
1) 생성자 내에서 가상 함수를 호출하면 이상 동작을 일으킬 수 있으며,
2) 자식 클래스마다 구현한 가상 함수에 따라 부모의 생성자가 바뀌기 때문에 일관성이 없다.
C++과 C#의 차이
C++과 C#에서는 동작이 다르다.
C++에서는 각 클래스의 생성자가 실행되면 객체의 런타임 타입이 변경된다.
C#에서는 런타임을 고려하여 함수를 호출한다.
부모 생성자에서 추상 함수를 호출한다면 C++은 런타임 오류가 발생하지만,
C#은 정상적으로 자식의 오버라이딩 함수가 호출될 것이다.
결론
- 생성자 내에서는 가급적 가상 함수를 호출하지 말자.
- 자식 클래스의 생성자는 부모 클래스의 기본 생성자 이후에 호출된다는 점을 기억할 것.
'🌍 C# Study > 이펙티브 C#' 카테고리의 다른 글
[18] 반드시 필요한 제약조건만 설정하라 (0) | 2021.04.26 |
---|---|
[17] 표준 Dispose 패턴을 구현하라 (0) | 2021.04.26 |
[15] 불필요한 객체를 만들지 말라 (0) | 2021.04.25 |
[14] 초기화 코드가 중복되는 것을 최소화하라 (0) | 2021.04.25 |
[13] 정적 클래스 멤버를 올바르게 초기화하라 (0) | 2021.04.25 |