클래스 초기화
아래의 코드를 보고 설명하겠다.
class User(val nickname : String)
보통 클래스의 모든 선언은 중괄화 '{ }' 사이에 들어간다.
하지만, 이 클래스 선언에는 중괄호가 없고 괄호 사이에 val 선언만 존재한다.
그 이유는 무엇일까?
이렇게 클래스 이름 뒤에 오는 괄호로 둘러 싸인 코드를 주 생성자 (primary constructor)라고 부른다.
주 생성자는 두 가지 목적에 쓰인다.
- 생성자 파라미터를 지정한다
- 그 생성자 파라미터에 의해 초기화되는 프로퍼티를 정의한다.
위 코드처럼 간단한 클래스 선언이 아닌, 같은 목적을 달성할 수 있는 가장 명시적인 선언으로 푼 코드를 확인해보자.
class User constructor(_nickname : String) { // 밑줄(_)은 프로퍼티와 생성자 파라미터를 구분해준다.
private val nickname : String
init {
nickname = _nickname
}
}
새로운 키워드 constructor 이랑 init 을 볼 수 있다.
- constructor : 주 생성자나 부 생성자 정의를 시작할 때 사용한다.
- init : 초기화 블록을 시작한다. 초기화 블록에는 클래스의 객체가 만들어질 때(인스턴스화될 때) 실행될 초기화 코드가 들어간다.
초기화 블록은 주 생성자와 함께 사용된다.
주 생성자는 제한적이기 때문에 별도의 코드를 포함할 수 없으므로 초기화 블록이 필요하다.
[Java]
class User() {
String nickname;
public User(String nickname) {
this.nickname = nickname;
}
}
위 자바 코드를 아래 코틀린 코드와 비교해서 보면 좋을 거 같다.
[Kotlin]
class User (_nickname : String) { // 파라미터가 하나 뿐인 주 생성자
val nickname = _nickname // 프로퍼티를 주 생성자의 파라미터로 초기화 한다.
}
코틀린에서 위 코드는 클래스를 정의하는 여러 방법 중 하나다.
프로퍼티를 초기화하는 식이나, 초기화 블록 안에서만 주 생성자의 파라미터를 참조할 수 있다는 점을 유의하라.
또한, 앞에 별다른 애노테이션이나 가시성 변경자가 없다면 constructor를 생략해도 된다.
위 코드보다 동일하지만, 더 간결한 방법이 있다.
val 를 추가하는 방식으로 프로퍼티 정의와 초기화를 간략히 쓸 수 있다.
// 가장 간결!
class User(val nickname : String) // 'val' 은 이 파라머티에 상응하는 프로퍼티가 생성된다는 뜻이다.
또한, 생성자 파라미터에도 디폴트 값을 정의할 수가 있다.
class User(val nickname : String,
val isSubscribed Boolean = true) // 생성자 파라미터에 대한 디폴트 값을 제공
클래스의 인스턴스를 만들려면 new 키워드 없이 생성자를 직접 호출하면 된다.
val chief = User("정민")
println(chief.isSubscribed)
//true
클래스에 기반 클래스가 있다면, 주 생성자에서 기반 클래스의 생성자를 호출해야 할 필요가 있다.
open class User(val nickname : String) {...}
class TwitterUser(nickname: String) : User(nickname) { ...}
클래스를 정의할 때, 별도로 생성자를 정의하지 않으면 컴파일러가 자동으로 아무 일도 하지 않는 인자가 없는 디폴트 생성자가 만들어진다.
open class Button // 인자가 없는 디폴트 생성자가 만들어짐.
그리고 위 코드를 확인 해보면 Button 생성자는 아무 인자도 받지 않지만, Button 클래스를 상속한 하위 클래스는 반드시 Button 클래스의 생성자를 호출해야 한다.
class RadioButton : Button()
위 코드를 보면 빈 괄호가 들어간 것을 확인할 수 있다.
생성자 인자가 있다면 괄호 안에 인자가 들어가겠지만, 기반 클래스의 이름 뒤에는 꼭 괄호를 넣어야 한다.
반면, 인터페이스는 생성자가 없기 때문에 어떤 클래스가 인터페이스를 구현하는 경우, 그 클래스의 상위 클래스 목록에 있는 인터페이스 이름 뒤에는 아무 괄호도 없다.
어떤 클래스를 클래스 외부에서 인스턴스화 하지 못하게 막고 싶다면, 모든 생성자를 private 으로 만들면 된다.
class Secretive private constructor() {} // 이 클래스의 (유일한) 주 생성자는 비공개가 됨.
'Language > Kotlin' 카테고리의 다른 글
[Kotlin] zip(), mapIndexed(), filterNotNull() (0) | 2023.07.09 |
---|---|
[Kotlin IN ACTION] - 코틀린 생성자(2) (0) | 2022.07.29 |
[Kotlin IN ACTION] - Kotlin sealed 클래스 (0) | 2022.07.25 |
[Kotlin IN ACTION] - Kotlin 접근 제어자(가시성 변경자) / 내부 클래스 / 중첩 클래스 (0) | 2022.07.25 |
[Kotlin IN ACTION] - Kotlin open / final / abstract 상속 제어(접근) 변경자 (0) | 2022.07.22 |