클래스와 오브젝트#3 - 클래스 생성자
코틀린에서도 자바와 같이 생성자를 하나 이상 선언할 수 있다.
다만 다른 점이 있는데, 코틀린에서 생성자는 주 생성자
와 부 생성자
로 구분된다.
먼저 주 생성자
Primary Constructor를 살펴보자.
주 생성자는 클래스 선언문의 header영역의 한 부분으로 class 이름 다음에 위치한다.
class User constructor(val nickname: String) {}
또한 별다른 어노테이션이나 가시성 변경자(visibility modifier)가 없는 경우 constructor
키워드는 생략 가능하며,
별다른 초기화할 코드가 없다면 class body부분인 중괄호도 생략 가능하다.
//constructor keyword생략 가능
class User (nickname: String) {}
//class body부분 생략 가능
class User (nickname: String)
주 생성자는 다음과 같은 역할을 한다.
- 생성자 파라미터를 선언
- 그 생성자 파라미터에 의해 초기화 되는 프로퍼티를 정의
주 생성자는 파라미터(or프로퍼티)선언 외에 초기화에 필요한 코드를 추가 할 수 없기 때문에,
초기화 블록(initializer blocks)
이라는 것을 사용할 수 있다.
초기화 블록은 init
키워드로 블록으로 클래스 객체의 instance가 생성될때 주 생성자와 함께 사용되며
필요하다면 class body안에 여러개 선언할 수 있다.
초기화 블록없이 class body안에서 주생성자로 전달된 파라미터를 이용하여 프로퍼티를 초기화 할수 있다.
주 생성자 안에 val
을 추가하는 방식으로 프로퍼티 정의와 초기화를 한번에 할 수 있다.
class User(val nickname:String)
또한 함수 파라미터와 마찬가지로 생성자 파라미터에도 디폴트 값을 정의 할 수 있다.
class User(val nickname:String, val isSubscribed: Boolean = true)
클래스의 인스턴스를 만들려면 new 키워드 없이 생성자를 직접 호출하면 된다.
- 클래스를 정의할 때 별도로 생성자를 정의하지 않으면 컴파일러가 자동으로 아무 일도 하지 않는 인자가 없는 디폴트 생성자를 만들어준다.
//인자가 없는 디폴트 생성자 open class Button
아무 인자도 받지 않지만, Button 클래스를 상송한 하위 클래스는 반드시 Button클래스의 생성자를 호출해야 한다.
//인자가 없는 클래스를 상속받을 때 class RadioButton : Button()
또한 상위 클래스의 생성자에 파라미터가 선언되어 있다면 인자도 넘겨야 한다.
부 생성자
Secondary Constructor
일반적으로 코틀린에서는 생성자가 여럿 있는 경우가 자바보다 훨씬 적다. 새로운 생성자가 필요한 상황 중 상당수는 코틀린의 디폴트 파라미터 값과 이름붙은 인자 문법을 사용해 해결할 수 있다.
- Tip. 인자에 대한 디폴트 값을 제공하기 위해 부 생성자를 여럿 만들지 말고 파라미터의 디폴트 값을 생성자 시그니처에 직접 명시하자.
하지만 인자의 갯수가 다른 부 생성자가 필요한 경우 다음과 같이 정의할 수 있다.
아래는 주 생성자가 없는 View객체를 상속하는 부 객체에서 상위객체를 초기화 하는 방식의 여러 예이다.
- 클래스에 주 생성자가 없다면 모든 부 생성자는 반드시 상위 클래스를 초기화하거나 다른 생성자에게 생성을 위임해야 한다.
이 객체를 상속할때 하위 객체의
부 생성자
에서는super()
키워드를 통해 자신에 대응하는 상위 클래스 생성자를 호출할 수 있다.
class MyView: View {
constructor(ctx:String): super(ctx) {
//...
}
constructor(ctx: String, attr: String): super(ctx, attr) {
//...
}
}
또한 this()
키워드를 통해 자신의 다른 부생성자를 호출하여 생성자 처리를 위임(delegate)
할 수 있다.
class MineView: View {
constructor(ctx: String):this(ctx, "strong") {
//부 생성자
}
constructor(ctx: String, attr: String): super(ctx) {
//부 생성자
}
}