확장 속성은 클래스에 대한 확장으로, 상태(재저장 필드)를 추가할 수 없고 getter와 setter를 추가할 수 있습니다. 자바에서는 이러한 기능을 지원하지 않으며, 유틸리티 메소드를 작성하는 것이 유사한 기능입니다. 기능을 추가하기 위해 정적 메소드나 래퍼 객체를 사용하는 것이 역사적으로 필요했습니다.
문제: 외부 클래스에 종종 필요한 속성이 부족한 경우가 많습니다. 캡슐화를 파괴하지 않고 클래스의 기능을 간결하고 안전하게 확장하고 싶습니다.
해결책: 코틀린에서는 일반 속성처럼 보이는 확장 속성을 선언할 수 있지만 함수의 형태로 구현됩니다. 이를 통해 소스 코드에 접근할 수 없는 타입들을 편리하게 확장할 수 있습니다.
코드 예시:
val String.firstChar: Char get() = this[0] println("Kotlin".firstChar) // K
주요 특징:
확장 속성에 재저장 필드(상태)를 추가할 수 있나요?
아니요, 확장 속성은 값을 즉석에서 계산할 뿐이며 상태를 저장할 수 없습니다.
확장 속성이 상속된 클래스에서 속성을 재정의할 수 있나요?
아니요, 확장 속성(및 확장 함수)은 본질적으로 정적입니다: 재정의되거나 가상일 수 없습니다.
확장 속성이 어떻게 컴파일되며, 왜 일반 속성과 유사한 구문이 아닐까요?
확장 속성은 실제로 정적 getter(및/또는 setter) 함수로 컴파일됩니다. 이들은 클래스의 엔티티에 포함되지 않으며, 선언된 파일의 컨텍스트에서만 보입니다.
부정적 사례
개발자가 표준 Android View에 대한 상태 "방문 여부"를 저장하기 위해 확장 속성을 추가하려고 했습니다:
var View.isVisited: Boolean get() = ... set(value) { ... } // 오류: 저장 불가
장점:
단점:
긍정적 사례
String에 대한 확장 속성을 구현하여 확장된 형식을 얻었습니다:
val String.asTitle: String get() = this.replaceFirstChar { it.uppercase() }
장점:
단점: