Kotlin

[Kotlin] 보조 생성자(secondary constructors)에서의 초기화 블록(initializer blocks) 실행 타이밍

yujinius 2024. 7. 22. 16:50

 

보조 생성자(Secondary constructors)에서
초기화 블록(initializer blocks) 실행 타이밍은 언제일까?

 

정답은 일단 보조 생성자 첫 문장 접근 순간! 이다.

이제 왜 그런건지 차근차근 알아보자.

  • 이니셜라이저 블록의 코드는 기본 생성자의 일부가 됨!!
  • 기본 생성자에 대한 위임은 보조 생성자의 첫 번째 문장에 접근하는 순간에 발생하므로, 모든 이니셜라이저 블록 및 속성 초기화 코드가 보조 생성자의 본문 이전에 실행
  • 클래스에 기본 생성자가 없더라도 위임은 암시적으로 발생하며, 이니셜라이저 블록은 여전히 실행됨
class Constructors {
    init {
        println("Init block")
    }

    constructor(i: Int) {
        println("Constructor $i")
    }
}
// ▼ 출력
Init block // 보조 생성자 이전에 실행됨!!
Constructor 1

컴파일러가 public 기본 생성자 추가하는 경우

  • 추상 클래스가 아닌 클래스가 어떤 생성자도 선언하지 않으면, 매개변수가 없는 기본 생성자가 public으로 생성됨.
  • 클래스에 public 생성자가 없도록 하려면 기본 가시성이 없는 빈 기본 생성자를 선언하기
  • class DontCreateMe private constructor() { /*...*/ }

컴파일러가 기본 생성자 추가하는 경우

  • JVM에서는 기본 생성자 매개변수에 기본값이 모두 설정된 경우, 매개변수가 없는 추가 생성자가 생성되며, 이는 기본값을 사용
  • 이를 통해 Jackson이나 JPA와 같은 라이브러리와 Kotlin을 더 쉽게 사용할 수 있음
    • 위처럼 모든 매개변수에 기본값을 지정하면 Kotlin 컴파일러는 다음 2가지 생성자를 자동 생성
      1. 기본 생성자
        • 이 생성자는 매개변수가 없으며, customerName에 빈 문자열을 기본값으로 할당
      2. Customer() { this.customerName = "" }
      3. 명시적 생성자
        • 이 생성자는 customerName 값을 매개변수로 받아서 필드에 할당
      4. Customer(customerName: String) { this.customerName = customerName }
    • 클래스 정의에 모든 매개변수가 기본값을 가지고 있다면, 해당 클래스는 기본 생성자와 매개변수가 있는 생성자 둘 다 가지게 되어 아래 같이 사용 가능
    • val customer1 = Customer() // 기본 생성자 사용 - 빈 문자열 val customer2 = Customer("Alice") // 명시적 생성자 사용
  • class Customer(val customerName: String = "")

컴파일러가 기본 생성자 추가하지 않는 경우

class Customer(val customerName: String = "", val customerMoney: Int)
  • 이 경우 기본값이 없는 customerMoney라는 필드가 존재하므로, 컴파일러는 매개변수가 없는 기본 생성자를 자동으로 생성하지 않음
  • 기본 생성자가 생성되기 위해서는 모든 매개변수에 기본값이 있어야 함
  • 이 클래스에는 매개변수가 없는 생성자는 없고, customerMoney 값을 반드시 받아야 하는 생성자만 존재. 이 생성자는 customerName의 기본값을 빈 문자열로 설정하거나, 명시적으로 값을 전달받을 수 있음.
  • 생성자는 아래와 같이 생성됨
    1. 명시적 생성자
      • customerName에 기본값을 제공하지만, customerMoney에 대해서는 값을 반드시 받아야 함
    2. Customer(customerName: String = "", customerMoney: Int)
    • 아래와 같이 사용
    • val customer1 = Customer(customerMoney = 1000) // customerName은 기본값 ""을 사용 val customer2 = Customer("Alice", 2000) // 명시적 값을 모두 제공

컴파일 오류 나는 경우

  • 매개변수가 없는 기본 생성자는 생성되지 않기 때문에, 다음과 같은 코드는 컴파일 오류가 발생
  • val customer3 = Customer() // 컴파일 오류: customerMoney 매개변수가 필요합니다

 

🌟 보조 생성자(Secondary constructors)에서
초기화 블록(initializer blocks) 실행 타이밍은 보조 생성자 첫 문장 접근 순간!

🌟 컴파일러가 기본 생성자 추가하기 위한 조건은 모든 매개변수에 기본 값이 있는 경우!