Effective Kotlin - Properties should represent state, not behavior
2021. 8. 19. 00:43ㆍComputer
코틀린의 속성은 자바의 필드와 비슷해 보입니다. 그렇지만, 서로 다른 컨셉을 갖고 있습니다.
//Kotlinproperty
var name:String?=null
//Javafield
String name=null;
같은 방식으로 사용할지라도, 코틀린의 속성은 좀 더 많은 것을 할 수 있다.
property 선언에 대한 전체 구문
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
Custom Get, Set ( var )
var name: String? = null
get() = field?.toUpperCase()
set(value) { if(!value.isNullOrBlank()) { field = value }
Custom Get ( val )
val fullName: String?
get() = "$name $surname"
Backing Fields
필드는 커스터마이징하게 선언할 수 없습니다. 다만, 속성에 지원 필드가 필요할경우 자동으로 생성합니다. 이 지원 필드는 field 식별자를 사용하여 접근자에서 참조할 수 있습니다.
var counter = 0 // the initializer assigns the backing field directly
set(value) {
if (value >= 0)
field = value
// counter = value // ERROR StackOverflow: Using actual name 'counter' would make setter recursive
}
Different with function?
코틀린에서의 프로퍼티는 해당 객체의 상태를 의미한다면, 함수는 해당 객체의 행위를 의미합니다.
// property
val isEmpty: Boolean
get() = amount == 0
// function
fun isEmpty(): Boolean {
return amount == 0
}
생각해봅시다.
항상 속성을 이용하는 방식이 좋을까요?
class FruitBucket(
val price: Int,
val discount: Int,
var amount: Int
) {
val isEmpty: Boolean
get() = amount == 0
val salePrice: Int
get() = price - discount
}
다음의 코드를 개선을 한다면 다음처럼 개선을 할 수 있습니다.
접근할때마다 매번 연산을 하는것은 비효율 적이기 떄문이지요.
class FruitBucket(
val price: Int,
val discount: Int,
var amount: Int
) {
val isEmpty: Boolean
get() = amount == 0
val salePrice: Int = price - discount
}
데이터를 보유하지 않은채, 해당 속성을 사용할 수 있다.
어떤 연유로, date 유형을 사용하지 못하는 경우에도, 코틀린의 속성 기능을 사용해서, Date유형의 데이터를 저장하는 것이 아니라, 다른 값을 이용해서, Date 유형의 값을 사용하 수 있다. ( 직렬화등을 할 경우, millis 에 대해서만 값을 갖고 있다가, 사용할때는, Date 형태로 변환하는 형태 )
var date: Date
get() = Date(millis)
set(value) {
millis = value.time
}
속성은 단순 필드가 아닌, 접근자로서도 사용할 수 있습니다.
valContext.preferences:SharedPreferences
get() = PreferenceManager.getDefaultSharedPreferences(this)
valContext.inflater:LayoutInflater
get() = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
valContext.notificationManager:NotificationManager
get() = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
속성기능은 만능일까요?
순환, 반복 등과 같은 특정한 로직이 들어가거나, 알고리즘적인 부분이 주입된 속성은 올바른 사용법이 아닙니다.
// Don't do this !
val Tree<Int>.sum:Int
get() = when (this) {
is Leaf -> value
is Node -> left.sum + right.sum
}
Property (속성)은 일반적으로 상태를 나타내거나, 설정하는 데에만 사용해야합니다.
속성을 사용하기보다 함수를 사용하길 권장하는 예시를 드립니다.
- O(1) 보다 복잡도가 높을 경우 ( 계산 비용이 많이 들경우 )
- 단순 작업 (로깅, 요소 업데이트 등) 이상의 비즈니스 로직을 담을 경우
- 멤버를 두 번 연속 호출시, 다른 결과가 출력될 경우.
- Int.toDouble() 과 같이 관례적 표현의 중복이 생길 경우.
- Getter 에서 속성의 상태를 변경할 경우.
참고
- https://kotlinlang.org/docs/properties.html#backing-fields
- Effective Kotlin
반응형
'Computer' 카테고리의 다른 글
Effective Kotlin - Minimize elements visibility (0) | 2021.10.14 |
---|---|
Effective Kotlin - Respect the contract of compareTo (0) | 2021.10.07 |
Effective Kotlin - Data Modifer (0) | 2021.09.30 |
Effective Kotlin - 변수의 범위 최소화 (0) | 2021.07.22 |
[Unity] KaKao Plugin 만들기 (0) | 2017.02.24 |