1. 코틀린 프로퍼티의 기본 개념
- 코틀린에서 프로퍼티(Property)는 객체의 상태를 나타내는 핵심 요소입니다.
- 자바에서 프로퍼티란 필드와 게터/세터 메서드를 결합한 개념으로, 보다 간결하고 표현력 있는 코드를 작성할 수 있게 해줍니다.
- 코틀린은 프로퍼티를 언어 기본 기능으로 제공합니다.
- 코틀린은 프로퍼티를 선언할 때 크게 두 가지 유형으로 구분합니다.
var: 가변(mutable) 프로퍼티로, 값을 읽고 쓸 수 있습니다.val: 읽기 전용(read-only) 프로퍼티로, 초기화 후에는 값을 변경할 수 없습니다.
1.1 Java와 비교해서 이해하기
- 프로퍼티는 빈의 상채를 나타내는 중요한 요소입니다.
- 자바에서는 프로퍼티를 필드와 게터/ 세터 메서드로 구현합니다.
- 코틀린에서는 프로퍼티를 선언할 때
var또는val키워드를 사용하여 간결하게 표현합니다. - val 프로퍼티를 선언한느 경우, 이는 자바에서 private final 필드와 public getter 메서드와 동등합니다.
- var 프로퍼티를 선언하는 경우, 이는 자바에서 private 필드와 public getter/setter 메서드와 동등합니다.
- 즉 코틀린의 프로퍼티는 자바의 필드와 게터/세터 메서드를 결합한 형태로, 더 간결하고 직관적인 문법을 제공합니다.
1.2 기본 프로퍼티 선언 및 사용
class Address {
var name: String = "Holmes, Sherlock"
var street: String = "Baker"
var city: String = "London"
var state: String? = null
var zip: String = "123456"
}
- 코틀린에서는 클래스의 프로퍼티를 위와 같이 선언합니다.
fun copyAddress(address: Address): Address {
val result = Address() // 코틀린에는 'new' 키워드가 없습니다
result.name = address.name // 접근자(accessor)가 호출됩니다
result.street = address.street
// ...
return result
}
- 프로퍼티를 사용할 때는 단순히 이름으로 참조하면 됩니다.
2. 게터와 세터 (Getters and Setters)
- 코틀린 프로퍼티의 전체 문법은 다음과 같습니다:
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
- 초기화 식, 게터, 세터는 모두 선택사항입니다.
- 타입은 초기화 식이나 게터의 반환 타입에서 추론될 수 있다면 생략 가능합니다.
var initialized = 1 // Int 타입으로 추론됨, 기본 게터와 세터가 제공됨
2.1 이름 규칙
- 이름이 is로 시작하는 프로퍼티의 게터는 get이 붙지 않고 원래 이름을 그대로 사용합니다.
- 세터는 is를 set으로 바꾼 이름을 사용합니다.
예시
class Person(
val name: String,
var isStudent: Boolean
)
fun main() {
val person = Person("John", true)
println(person.name) // "John"
println(person.isStudent) // true
person.isStudent = false // 세터 호출
println(person.isStudent) // false
}
println(person.name)에서 프로퍼티 이름을 직접 사용하면 코틀린이 자동으로 게터를 호출합니다.person.isStudent = false에서 프로퍼티 이름을 직접 사용하면 코틀린이 자동으로 세터를 호출합니다.
2.2 커스텀 접근자 (Custom Accessors)
- 코틀린에서는 프로퍼티에 대한 커스텀 접근자를 정의할 수 있습니다.
- 커스텀 게터를 정의하면, 프로퍼티에 접근할 때마다 해당 코드가 실행됩니다.
- 어떤 프로퍼티가 같은 객체 안의 다른 프로퍼티에서 계산된 결과인 경우 커스텀 접근자를 사용합니다.
예시
class Rectangle(val width: Int, val height: Int) {
val area: Int // 게터의 반환 타입에서 추론 가능하므로 타입 생략 가능
get() = this.width * this.height
}
val area get() = this.width * this.height
- 타입이 추론 가능한 경우 더 간결하게 작성할 수 있습니다
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value) // 문자열을 파싱하여 다른 프로퍼티에 값을 할당
}
- 커스텀 세터도 정의할 수 있으며, 프로퍼티에 값을 할당할 때마다 호출됩니다:
- 관례적으로 세터의 파라미터 이름은
value를 사용하지만, 원하는 다른 이름을 선택할 수도 있습니다.