프로퍼티와 필드
프로퍼티 선언
코틀린에서 클래스는 프로퍼티를 가질 수 있다
var키워드로 변경 가능하게 선언
val키워드로 읽기 전용 선언
class Address {
var name: String = ...
var street: String = ...
var state: String? = ...
}
자바 필드처럼 이름으로 프로퍼티 참조 가능
fun copyAddress(address: Address): Address {
val result = Address() // 코틀린에 'new'키워드 없음
result.name = address.name // 접근자 실행
result.street = address.street
// ...
return result
}
Getters와 Setters
프로퍼티 선언의 전체 구문은 다음과 같다
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
initializer, getter, setter는 선택사항 / 프로퍼티 타입은 initializer의 리턴타입에서 유추할 수 있으면 생략 가능
예제:
var allByDefault: Int? // 에러(initializer-초기화) 필요, 기본 getter와 setter 적용
var initialized = 1 // Int타입을 갖고, 기본 getter와 setter
읽기 전용 프로퍼티 선언은 변경가능 프로퍼티 선언과 두 가지가 다르다
var대신에 val로 시작 / setter를 허용하지 않는다
val simple: Int? // Int타입이고, 기본 getter, 생성자에서 초기화해야 함
val inferredType = 1 // Int타입이고, 기본 getter
일반 함수처럼 프로퍼티 선언에 커스텀 접근자를 작성할 수 있다 / 다음은 커스텀 getter의 예
val isEmpty: Boolean
get() = this.size == 0
커스텀 setter
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value) // 문자열을 파싱해서 다른 프로퍼티에 값을 할당
}
setter파라미터의 이름을 value로 하는것이 관례인데, 선호하는 다른 이름 가능
getter에서 타입을 추론할 수 있으면 프로퍼티 타입을 생략할 수 있다
val isEmpty get() = this.size == 0 // Boolean 타입
프로퍼티의 기본 구현을 바꾸지 않고 애노테이션을 붙이거나 접근자의 가시성을 바꾸고 싶다면 몸체 없는 접근자 정의
var setterVisibility: String = "abc"
private set // setter를 private로 하고 기본 구현을 가짐
var setterWithAnnotation: Any? = null
@Inject set // setter에 @Inject애노테이션 사용
지원 필드
코틀린 클래스는 필드를 가질 수 없다 / 때떄로 커스텀 접근자를 사용할 때 지원 필드가 필요
이런 목적으로 코틀린은 field식별자로 접근할 수 있는 지원 필드를 자동으로 제공
var counter = 0 // 초기값을 지원 필드에 직접 쓴다
set(value) {
if(value >= 0) field = value
}
field식별자는 오직 프로퍼티의 접근자에서만 사용 가능
접근자의 기본 구현을 적어도 한 개 이상 사용하거나 또는 커스텀 접근자에서 field식별자로 접근할 경우,
프로퍼티를 위한 지원 필드 생성
다음과 같은 경우는 지원 필드가 없다
val isEmpty: Boolean
get() = this.size == 0
컴파일 타임 상수
컴파일 시점에 알아야 할 프로퍼티 값을 const수식어를 이용해서 컴파일 타임 상수로 표시할 수 있다
그런 프로퍼티는 다음 조건을 충족해야함
- 최상위 또는 오브젝트의 멤버
- String이나 기본 타입 값으로 초기화
- 커스텀 getter가 아님
이런 프로퍼티는 애노테이션에서 사용할 수 있다
const val SUBSYSTEM_DEPRECATED: String = "this subsystem is deprecated"
@Deprecated(SUBSYSTEM_DEPRECATED) fun foo { ... }