주 생성자
코틀린에서의 클래스는 생성자를 주 생성자와 보조 생성자로 구분합니다. 한 클래스 안에 주 생성자만 선언할 수도 있고 보조 생성자만 선언할 수도 있습니다. 물론 둘 다 선언 가능합니다.
주 생성자는 constructor 키워드로 클래스 선언부에 선언합니다. 주 생성자 선언은 필수는 아니며 한 클래스에 하나만 가능합니다.
주 생성자 선언
class User constructor() {
}
주 생성자를 선언할 때 constructor 키워드는 생략할 수 있습니다.
constructor 키워드 생략 예
class User() {
}
만약 개발자가 클래스의 주 생성자를 선언하지 않으면 컴파일러가 매개변수가 없는 주 생성자를 자동으로 추가합니다.
매개변수가 없는 주 생성자 자동 선언
class User() {
}
주 생성자의 매개변수
주 생성자를 선언할 때 필요에 따라 매개변수를 선언할 수도 있습니다.
주 생성자의 매개변수
class User(name: String, count: Int){
}
앞의 코드는 User 클래스를 선언하면서 주 생성자에 매개변수를 2개 선언하였습니다. 그러면 객체를 생성할 때 매개변수의 타입과 개수에 맞는 인자를 전달해야 합니다.
매개변수가 있는 생성자 호출
val user = User("kkang", 10)
주 생성자의 본문 – init 영역
주 생성자를 이용해 객체를 생성할 때 특정한 로직을 수행할 수 있습니다. 그런데 주 생성자의 실행 영역인 본문을 다음처럼 추가하면 오류가 발생합니다.
주 생성자 중괄호 때문에 오류 발생
class User(name: String, count: Int){
// 주 생성자 본문
}{ // 오류
// 클래스 본문
}
보통 클래스나 함수의 본문(실행 영역)은 중괄호 {}로 감싸지만 주 생성자에는 {}를 추가할 수 없습니다. 왜냐하면 주 생성자는 클래스 선언부에 있기 때문입니다. 이럴 때 init 키워드를 이용해 주 생성자의 본문을 구현할 수 있습니다.
코틀린의 클래스 안에서 init 키워드로 지정한 영역은 객체를 생성할 때 자동으로 실행됩니다. 클래스에서 init 영역은 꼭 선언할 필요는 없으므로 주 생성자의 본문을 구현하고 싶을 때 사용합니다.
init 영역은 주 생성자뿐만 아니라 잠시 후에 다루는 보조 생성자로 객체를 생성할 때도 실행됩니다. 하지만 보조 생성자는 클래스 안에 선언하므로 {}를 이용해 본문을 지정할 수 있습니다. 따라서 init 영역은 일반적으로 주 생성자의 본문을 구현하는 용도로 사용합니다.
init 키워드로 주 생성자의 본문 지정
class User(name: String, count: Int){
init {
println("i am init...")
}
}
fun main() {
val user = User("kkang", 10)
}
>> 실행결과
i am init...
User라는 클래스에 주 생성자를 선언하고 클래스 본문에 init 영역을 두어 주 생성자의 본문을 작성하였습니다. 이렇게 하면 main() 함수에서 User 클래스의 객체를 생성할 때 init 영역에 작성한 코드가 자동으로 실행됩니다.
생성자의 매개변수를 클래스의 멤버 변수로 선언하는 방법
생성자의 매개변수는 기본적으로 생성자에서만 사용할 수 있는 지역 변수입니다.
생성자의 매개변수를 init 영역에서 사용하는 예
class User(name: String, count: Int){
init{
println("name : $name, count : $count") // 성공
}
fun someFun(){
println("name : $name, count : $count") // 오류
}
}
위 코드에서는 주 생성자에 name, count 매개변수를 선언하였습니다. 그리고 이 변수를 init 영역과 someFun() 이라는 함수에서 사용하려고 합니다. 생성자를 호출할 때 init 영역이 실행되므로 이곳에서 생성자의 매개변수에 접근할 수 있습니다.
하지만 생성자의 매개변수는 지역 변수이므로 다른 함수에서는 사용할 수 없습니다. 만약 생성자의 매개변수를 클래스의 멤버 변수처럼 다른 함수에서 사용해야 한다면 다음처럼 작성해야 합니다.
생성자의 매개변수를 다른 함수에서 사용하는 예
class User(name: String, count: Int){
// 클래스 멤버 변수 선언
var name: String
var count: Int
init{
// 클래스 멤버 변수에 생성자 매개변숫값 대입
this.name = name
this.count = count
}
fun someFun(){
println("name : $name, count : $count") // 성공
}
}
fun main(){
val user = User("kkang", 10)
user.someFun()
}
>> 실행결과
name : kkang, count : 10
클래스의 멤버 함수 someFun()에서 생성자의 매개변수를 이용하고자 클래스의 멤버 변수를 선언하고 주 생성자의 본문인 init 영역에서 매개변숫값을 클래스의 멤버 변수에 대입하였습니다.
그런데 이 방법 말고도 생성자의 매개변수를 클래스의 멤버 변수로 선언하는 방법이 있습니다. 이렇게 하면 코드를 조금 더 간단하게 작성할 수 있습니다. 주 생성자의 매개변수는 생성자 안에서만 사용할 수 있는 지역 변수지만 매개변수를 var나 val 키워드로 선언하면 클래스의 멤버 변수가 됩니다.
생성자의 매개변수를 클래스의 멤버 변수로 선언하는 방법
class User(val name: String, val count: Int){
fun someFun(){
println("name : $name, count : $count") // 성공
}
}
fun main(){
val user = User("kkang", 10)
user.someFun()
}
>> 실행결과
name : kkang, count : 10
원래 함수는 매개변수를 선언할 때 var나 val 키워드를 추가할 수 없습니다. 그런데 주 생성자에서만 유일하게 var나 val 키워드로 매개변수를 선언할 수 있으며 이렇게 하면 클래스의 멤버 변수가 됩니다. 따라서 위 코드에서 생성자의 매개변수 name과 count를 someFun()이라는 멤버 함수에서 사용할 수 있습니다.