프로퍼티와 필드
프로퍼티 선언
- var / val (읽기 전용) 키워드로 정의
- 필드 사용 : 필드명으로 참조
Getter와 Setter
완전한 프로퍼티 선언문
- 옵션 : 초기화, Getter, Setter
- 추론가능한 경우에는 프로퍼타 타입은 옵션
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
var allByDefault: Int? // 에러: initializer 필요. 기본 getter/setter 가짐
val simple: Int? // Int 타입. 기본 getter를 가짐. 생성자에서 반드시 초기화
커스텀 Getter/Setter
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value)
}
Kotlin 1.1부터 getter로부터 추론되는 경우 프로퍼티 타입을 생략 가능
val isEmpty get() = this.size == 0 // Boolean 타입
accessor의 기본 구현을 변현하지 않고 가시성 변경 / 어노테이션을 추가하고 싶은 경우, body 정의 없이 accessor만 정의 가능
var setterVisibility: String = "abc"
private set // setter는 private. 기본 구현을 가진다
var setterWithAnnotation: Any? = null
@Inject set // setter에 annotation을 추가
Backing 필드
Kotlin 클래스는 필드를 가질 수 없다. 사용자 지정 접근자를 사용할 때에는 Backing Filed가 있어야 한다.
- filed 식별자를 사용해서 액세스 할 수 있는 자동 Backing Filed 제공
- filed 식별자는 프로퍼티 accessor에서만 사용 가능
var counter = 0 // 초기화 값을 backing filed에 직접 작성
set(value) {
if (value >= 0) field = value
}
아래의 경우 backing field 가 없다
val isEmpty: Boolean
get() = this.size == 0
Backing 프로퍼티
'암묵적인 Backing Field' 스킴으로 적합하지 않는 경우, backing 프로퍼티를 가질 수 있다
private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
get() {
if (_table == null) {
_table = HashMap() // 타입 파라매터 유추
}
return _table ?: throw AssertionError("Set to null by another thread")
}
- 기본적인 getter/setter를 사용한 private 프로퍼티 접근은 함수 호출 오버헤드가 없도록 최적하되기때문에 Java와 같다
컴파일 타임 상수
컴파일시에 값을 알 수 있는 프로퍼티는 const
식별자를 사용. 어노테이션을 이용하여 사용 가능
요구 조건
- 최상위 레벨 혹은
object
String
타입 혹은 기본 타입 값으로 초기화- 커스텀 Getter 없음
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ... }
초기화 지연(Late-Initialized) 프로퍼티
일반적인 non-null 프로퍼티는 생성자에서 초기화해야한다.
예) 의존성 주입이나 단위 테스트의 설정 메소드에서 초기화할 수도 있다. 생성자에서 null 이외의 초기화를 할 수 없지만, 클래스 본문내의 프로퍼트 참조시에 null 체크를 하고싶지 않다
lateinit
식별자로 처리 가능
public class MyTest {
lateinit var subject: TestSubject
@SetUp fun setup() {
subject = TestSubject()
}
@Test fun test() {
subject.method() // 직접 접근
}
}
클래스 본문에 선언되고 커스텀 getter/setter가 없는 var 프로퍼티에만 사용 가능
lateinit
가 초기화되기 전에 접근시 초기화되지않았음을 알려주는 특수한 예외를 발생한다
프로퍼티 오버라이딩
프로퍼티 오버라이딩 참조
위임 프로퍼티
일반적인 부류의 프로퍼트는 Backing 필드로부터 값을 읽고 쓴다. 한편 커스텀 getter/setter를 갖는 프로퍼티는 프로퍼티 동작을 구현가능하다.
예. lazy values, 지정된 키로 맵 읽기, 데이터베스 접근, 접근시 리스너에게 알림
이러한 일반적인 행위는 위임 프로퍼티를 사용해 라이브러리로 구현 가능