728x90
이펙티브 코루틴을 요약한 내용입니다
- 명시적으로 긴 코드를 사용할 때가 있음
- 함수와 프로퍼티를 지역 또는 톱레벨 변수가 아닌 다른 리시버로부터 가져온다는 것을 나타낼 때
class User: Person() { private var beersDrunk: Int = 0 fun drinkBeers(num: Int) { this.beersDrunk += num } }
- 확장 리시버를 명시적으로 참조하게 할 수 있음
- 리시버를 명시적으로 표시하지 않은 퀵소트 구현
fun <T: Comparable<T>> List<T>.quickSort(); List<T> {
if (size < 2) {
return this
}
val pivot = first()
val (smller, bigger) = drop(1).partition { it < pivot }
return smaller.quickSort() + pivot + bigger.quickSort()
}
- 명시적으로 표현한 퀵소트
fun <T: Comparable<T>> List<T>.quickSort(); List<T> {
if (size < 2) {
return this
}
val pivot = this.first()
val (smller, bigger) = this.drop(1).partition { it < pivot }
return smaller.quickSort() + pivot + bigger.quickSort()
}
- 두 함수의 사용에는 차이가 없음
listOf(3, 2, 5, 1, 6).quickSort()
listOf("C", "D", "A", "B").quickSort()
여러 개의 리시버
- 스코프 내부에 둘 이상의 리시버가 있는 경우 리시버를 명시적으로 나타내면 좋음
- apply, with, run 함수를 사용할때
- create에서 받은 name이 아닌 Node의 name 사용
class Node(val name: String) { fun makeChild(childName: String) = create("$name.$childName").apply { print("Created ${name}") } fun create(name: String): Node? = Node(name) } fun main() { val node = Node("parent") node.makeChild("child") // Created partent 출력 }
- 명시적으로 리시버를 붙이는 경우
class Node(val name: String) {
fun makeChild(childName: String) = create("$name.$childNamd").apply {
print("Created ${this?.name}")
}
fun create(name: String): Node? = Node(name)
}
fun main() {
val node = Node("parent")
node.makeChild("child") // Created parent.child 출력
}
- also 함수의 파라미터 name을 사용했다면 이런 문제는 발생하지 않음
- also를 사용하면 명시적으로 리시버를 지정
- also, let을 사용하는 것이 nullable 값을 처리할 때 좋은 선택지
class Node(val name: String) { fun makeChild(childName: String) = create("$name.$childName").also { print("Created ${it?.name}") } fun create(name: String): Node? = Node(name) } fun main() { val node = Node("parent") node.makeChild("child") // Created parent.child 출력 }
- 리시버가 명확하지 않다면, 명시적으로 리시버를 적어 명확하게 해줘야 함
- 레이블 없이 리시버를 사용하면, 가장 가까운 리시버를 의미
- 외부에 있는 리시버를 사용하려면, 레이블을 사용해야 함
class Node(val name: String) { fun makeChild(childName: String) = create("$name.$childName").apply { print("Created ${this?.name} in ${this@Node.name}") } fun create(name: String): Node? = Node(name) } fun main() { val node = Node("parent") node.makeChild("child") // Created parent.child in parent 출력 }
- 명확하게 작성하면 코드를 안전하게 사용할 수 있음
- 가독성도 향상
정리
- 짧게 적을 수 있다는 이유만으로 리시버를 제거하지 말기
- 여러 개의 리시버가 있는 상황 등에서는 리시버를 명시적으로 적어주는 것이 좋음
- 리시버를 명시적으로 지정하면, 어떤 리시버의 함수인지를 명확하게 알수 있음
- 가독성 향상
728x90
'코틀린 스터디 > 이펙티브 코틀린' 카테고리의 다른 글
아이템17) 이름 있는 아규먼트를 사용하라 (0) | 2024.04.17 |
---|---|
아이템16) 프로퍼티는 동작이 아니라 상태를 나타내야 한다 (0) | 2024.04.17 |
아이템14) 변수 타입이 명확하지 않은 경우 확실하게 지정하라 (0) | 2024.03.19 |
아이템13) Unit?을 리턴하지 말라 (0) | 2024.03.12 |
아이템12) 연산자 오버로드를 할 때는 의미에 맞게 사용하라 (0) | 2024.03.08 |