728x90
반응형
- 코틀린의 프로퍼티는 자바의 필드와 비슷해보이지만 완전히 다른 개념
// kotlin
val name: String? = null
// java
String name = null;
- 공통점 : 데이터를 저장
- 프로퍼티는 더 많은 기능이 존재
- 기본적으로 프로퍼티는 사용자 정의 세터/게터를 가질 수 있음
var name: String? = null
get() = field?.toUpperCase()
set(value) {
if (!value.isNullOrBlank()) {
field = value
}
}
field 식별자
: 프로퍼티의 데이터를 저장해 두는 백킹 필드(backing field)에 대한 레퍼런스- 백킹 필드는 세터와 게터의 디폴트 구현에 사용되며 따로 만들지 않아도 디폴트로 생성 됨
- val을 사용해서 읽기 전용 프로퍼티를 만들 때는 field가 만들어지지 않음
- var을 이용해서 만든 프로퍼티는 게터와 세터를 정의할 수 있으며, 이러한 프로퍼티를
파생 프로퍼티(derived property)
라고 부름
- 코틀린의 모든 프로퍼티는 디폴트로 캡슐화되어 있음
- 표준 라이브러리 Date를 활용해 날짜를 저장한 상황
- 직렬화 문제 등으로 객체를 더 이상 이러한 타입으로 저장할 수 없게된 경우 (이미 프로젝트 전체에서 이 프로퍼티를 참조하는 상황이라면)
- 코틀린에서는 millis라는 별도의 프로퍼티로 옮기고, 이를 활용하여 date 프로퍼티를 저장하지 않고, 랩/언랩하도록 코드를 변경하기만 하면 됨
var date: Date
get() = Date(millis) // wrap
set(value) {
millis = value.time // unwrap
}
- 프로퍼티는 필드가 필요 없음. 개념적으로 접근자를 나타냄 (val의 경우 게터, var의 경우 게터와 세터)
- 따라서 코틀린은 인터페이스에도 프로퍼티를 정의할 수 있음
interface Person {
// 게터를 가질 것을 나타냄
val name: String
}
open Class SuperComputer {
open val theAnswer: Long = 42
}
class AppleComputer: SuperComputer() {
override val theAnswer: Long = 1_800_275_2273
}
- 프로퍼티는 본질적으로 함수이므로, 확장 프로퍼티도 만들 수 있음
- 하지만 함수를 완전헤 대체해서 사용하는 것은 좋지 않음
- 알고리즘의 동작을 나타내는 것은 좋지 않음
// 이렇게 하지 말자
val Tree<Int>.sum: Int
get() = when (this) {
is Leaf -> value
is Node -> left.sum + right.sum
}
// 이러한 처리가 필요한 경우 함수로 구현하자
fun Tree<Int>.sum: Int = when(this) {
is Leaf -> value
is Node -> left.sum() + right.sum()
}
- 원칙적으로 프로퍼티는
상태를 나태내거나 설정하기 위한 목적
으로 사용하는 것이 좋고. 다른 로직 등을 포함하지 않아야 함
프로퍼티 대신 함수를 사용하는 것이 좋은 경우
- 연산 비용이 높거나, 복잡도가 O(1)보다 큰 경우
- 관습적으로 프로퍼티를 사용할 때 연산 비용이 많이 필요하다고 생각하지 않음
- 비즈니스 로직을 포함하는 경우
- 관습적으로 코드를 읽을 때 프로퍼티가 로깅, 리스너 통지, 바인드된 요소 변경과 같은 단순한 동작 이상을 할 거라고 기대하지 않음
- 결정적이지 않은 경우
- 같은 동작을 연속적으로 두 번 했는데 다른 값이 나올 수 있다면, 함수를 사용하는 것이 좋음
- 반환의 경우
- 변환은 관습적으로 Int.toDouble()과 같은 변환 삼수로 이루어짐
- 따라서 이러한 변환을 프로퍼티로 만들면, 오해를 불러 일으킬 수 있음
- 게터에서 프로퍼티의 상태 변경이 일어나야하는 경우
- 관습적으로 게터에서 프로퍼티의 상태 변화를 일으킨다고 생각하지 않음
예를 들어 요소의 합계를 계산하려면, 모든 요소를 더하는 반복 처리가 필요한데 (상태가 아닌 동작)
선형 복잡도를 가지므로, 이는 프로퍼티가 아닌 함수로 정의하는 것이 좋음
표준 라이브러리에서도 다음과 같은 같이 함수로 정의되어 있음
val s = (1...100).sum()
728x90
반응형
'프로그래밍 노트 > Effective 시리즈' 카테고리의 다른 글
[Effective Kotlin] 5장. 객체 생성 (1) | 2023.12.17 |
---|---|
[Effective Kotlin] 3장. 재사용성(Reusability) (1) | 2023.11.23 |
[Effective Kotlin. 11] 가독성을 목표로 설계하라 (1) | 2023.11.01 |
[Effective Kotlin. 26] 함수 내부의 추상화 레벨을 통일하라 (0) | 2023.10.25 |
[Effective Kotlin. 36] 상속보다는 컴포지션을 사용하라 (0) | 2023.10.17 |