Kotlin에서 각 클래스는 하나의 기본 생성자(primary constructor)와 여러 개의 보조 생성자(secondary constructors)를 가질 수 있습니다. 생성자 위임은 보조 생성자가 반드시 기본 생성자를 직접 호출하거나 같은 클래스의 다른 보조 생성자를 호출해야 하는 메커니즘입니다(결국 기본 생성자를 호출하게 됩니다). 클래스가 다른 클래스를 상속할 경우, 자식 클래스의 각 보조 생성자는 필요할 경우 반드시 수퍼 클래스의 생성자를 명시적으로 위임해야 합니다.
Java에서 생성자는 this()나 super()를 통해 서로 직접 호출할 수 있으며, 다양한 조합으로 생성자를 오버로딩할 수 있습니다. Kotlin에서는 이 개념이 형식화되어 있으며, 클래스는 오직 하나의 기본 생성자만 가질 수 있고, 보조 생성자는 명시적으로 지정해야 하는 위임 로직을 사용할 수 있습니다.
위임이 잘못 구현되면 컴파일 오류가 발생할 수 있습니다: 기본 생성자가 선언되었을 경우 이를 호출하지 않거나, 상속된 클래스에서 기본 클래스에 기본 생성자가 없는 경우 슈퍼 생성자를 호출하지 않아야 합니다. 언제 init 블록이 호출되는지, 매개변수가 어떻게 전달되는지, 위임이 초기화 순서에 어떤 영향을 미치는지를 이해하는 것이 중요합니다.
기본 위임 예시:
class Person(val name: String) { constructor(name: String, age: Int) : this(name) { println("보조 생성자: $name, $age") } }
상속을 사용할 경우:
open class Parent(val name: String) class Child : Parent { constructor(name: String) : super(name) { println("자식 보조: $name") } }
보조 생성자가 아무 데도 위임하지 않을 수 있나요?
아니요, 컴파일러는 this(...)나 super(...)를 명시적으로 호출할 것을 요구하며, 그렇지 않으면 오류가 발생합니다.
보조 생성자를 사용할 경우 초기화 및 init 블록은 어떤 순서로 실행되나요?
항상 가장 먼저 기본 생성자와 init 블록이 호출되며, 그 다음 보조 생성자의 초기화 코드가 실행됩니다.
class Demo(val value: String) { init { println("init 블록") } constructor(value: String, code: Int) : this(value) { println("보조: $code") } } Demo("kotlin", 7) // 출력: // init 블록 // 보조: 7
자식이 부모의 보조 생성자가 있을 경우 기본 생성자만 호출할 수 있나요?
네, 하지만 반드시 super(...)를 통해 명시적으로 호출해야 하며, 보조 생성자는 자식에게 직접적으로 보이지 않습니다.
프로젝트에서 보조 생성자가 기본 생성자를 호출하지 않으면, 중요한 초기화(예: 필수 필드 설정)가 이루어지지 않아 런타임에서 버그와 크래시를 초래하게 됩니다.
장점:
단점:
모든 보조 생성자가 반드시 this(...)를 통해 위임하며, 필요한 초기화가 기본/초기화 블록에 중앙 집중화되어 구조가 명확하여 유지보수가 용이합니다.
장점:
단점: