클래스와 프로퍼티
작성
step 09(클래스)에서 적은 것이다.
클래스 한 줄
class KotlinPerson(val name: String, var age: Int)
풀어 쓰면 이렇다.
class KotlinPerson constructor(name: String, age: Int) {
val name = name
val age = age
}
constructor키워드는 생략할 수 있다.- 생성자 파라미터에
val이나var를 붙이면 그 자리에서 프로퍼티가 만들어진다. val프로퍼티는 getter 만,var프로퍼티는 getter 와 setter 가 자동으로 생긴다.- body 가 없으면
{}를 생략할 수 있다. - Java 클래스의 getter 와 setter 도 Kotlin 에서는
.필드로 부른다.
val junha = KotlinPerson("junha", 20)
junha.age = 30
println("junha = ${junha.name} ${junha.age}")
val leo = JavaPerson("leo", 20)
println("leo = ${leo.name}") // Java 의 getName() 을 .name 으로 쓴다
init, custom getter 와 setter, 부생성자
class KotlinPersonV2(name: String, var age: Int) {
// 초기화 시점에 한 번 호출된다
init {
if (age <= 0) {
throw IllegalArgumentException("나이는 ${age} 일 수 없습니다.")
}
println("init 블록 실행")
}
var name = name
set(value) {
field = value.uppercase()
}
get() = field.uppercase()
// 주생성자 외에 부생성자(secondary constructor)를 더 만들 수 있다
constructor(name: String) : this(name, 1) {
println("secondary constructor 1")
}
constructor() : this("이름 없음") {
println("secondary constructor 2")
}
fun isAdult(): Boolean {
return this.age >= 20
}
// 함수 대신 프로퍼티처럼 보이게 하는 custom getter
val isAdultV2: Boolean
get() {
return this.age >= 20
}
val isAdultV3: Boolean
get() = this.age >= 20
}
init블록은 객체를 만들 때 한 번 실행된다. 값 검증을 여기서 한다.- custom getter 나 setter 안에서
name이라고 쓰면 바로 옆의 getter 를 다시 불러 무한 루프가 된다. 자기 자신을 가리키는field(backing field)를 써야 한다. - 다만 이 방법도 굳이 쓰지 않는다. 필드를 바꿀 때는 업데이트 함수를 쓰기 때문에 setter 자체를 지양하고, 대문자로 바꿔 보여 주려면 그 요구사항을 담은 getter 를 따로 만드는 편이 낫다.
- 부생성자는
this(...)로 주생성자나 다른 부생성자를 불러야 하고, 체이닝되면println이 역순으로 실행된다. - 부생성자보다 default parameter 를 권장한다. 객체를 다른 객체로 변환할 때는 부생성자를 쓸 수 있지만 정적 팩토리 메서드가 더 낫다. Kotlin 정도 쓰면 부생성자를 쓸 일이 거의 없을 것 같다.
val cream = KotlinPersonV2()
// init 블록 실행
// secondary constructor 1
// secondary constructor 2
println(cream.isAdultV3)
요약
- 필드를 만들면 getter 와 setter 를 자동으로 만들어 준다. 이 필드와 getter, setter 를 합쳐 프로퍼티라고 부른다.
- 주생성자가 필수다.
constructor키워드로 부생성자를 더 만들 수 있지만 default parameter 를 추천한다.- 실제 메모리에 있는 것과 무관하게, 함수로 만들 수 있는 것을 프로퍼티인 것처럼 custom getter 로 둘 수 있다.
- custom getter 와 setter 에서 무한 루프를 막으려면 backing field 를 쓴다.