독서

[이펙티브 코틀린] 3장. 재사용성

오렌지색 귤 2024. 7. 8. 02:51
반응형

아이템 19. knowledge를 반복하여 사용하지 말라

 

생략

 

 

 

 

 

아이템 20. 일반적인 알고리즘을 반복해서 구현하지 말라

 

p. 123

 

STDLIB 살펴보기

https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/src/Module.md

 

kotlin/libraries/stdlib/src/Module.md at master · JetBrains/kotlin

The Kotlin Programming Language. . Contribute to JetBrains/kotlin development by creating an account on GitHub.

github.com

 

 

 

 

 

 

아이템 21. 일반적인 프로퍼티 패턴은 프로퍼티 위임으로 만들어라

 

p. 128

 

print 결과가 Marcin이 나오는 이유는?

val map:Map<String, Any> = mapOf(
    "name" to "Marcin",
    "kotlinProgrammer" to true
)
val name by map
print(name) // Marcin

 

1. 위임 프로퍼티 (delegated properties)

  • 코틀린은 프로퍼티를 다른 객체에 위임할 수 있는 기능을 제공한다. 이 기능은 by 키워드를 사용하여 구현된다.
  • val name by map 구문에서 name 프로퍼티의 값이 map 객체에 의해 제공된다.

 

2. Map의 확장 함수 getValue

  • 코틀린 표준 라이브러리에는 Map에 대해 getValue라는 확장 함수가 정의되어 있다.
  • 아래 확장 함수는 프로퍼티 위임 시 호출된다. 여기서 중요한 점은 getValue 함수가 Map의 키에 해당하는 값을 반환하는 역할을 한다는 것이다.
inline operator fun <V, V1 : V> Map<in String, V>.getValue(thisRef: Any?, property: KProperty<*>): V1 =
    getOrImplicitDefault(property.name) as V1

 

3. 프로퍼티 위임 과정

  • val name by map은 컴파일 시 다음과 같은 코드로 변환된다.
val name: String
    get() = map.getValue(this, ::name)
  • 여기서 map.getValue(this, ::name) 호출은 getValue 확장 함수를 사용하여 map에서 name 키에 해당하는 값을 가져오는 것이다.
  • ::nameKProperty 객체로, 프로퍼티의 이름을 제공하는 역할을 한다.

 

4. 구체적인 동작

  • map.getValue(this, ::name)가 호출되면, getValue 함수는 property.name을 사용하여 map에서 키를 찾는다.
  • property.namename 프로퍼티의 이름인 "name"을 반환한다.
  • 따라서 getOrImplicitDefault("name")map["name"]과 동일한 결과를 가져온다.
  • map["name"]의 값은 "Marcin"이므로 getValue"Marcin"을 반환한다.

 

 

 

 

 

아이템 22. 일반적인 알고리즘을 구현할 때 제네릭을 사용하라

 

p.130

 

@Retention(RetentionPolicy.RUNTIME) 을 통해서 제네릭을 런타임에 접근하도록 할 수도 있긴하다.

 

 

 

 

 

 

아이템 23. 타입 파라미터의 섀도잉을 피하라

 

생략

 

 

 

 

 

아이템 24. 제네릭 타입과 variance 한정자를 활용하라

 

In, Out 등의 Variance 개념

 

p.139

함수 타입을 사용할 때는 이처럼 자동으로 variance 한정자가 사용됩니다. 코틀린에서 자주 사용되는 것으로는 covarianct(out 한정자)를 가진 List가 있습니다. 이는 variance 한정자가 붙지 않은 MutableList와 다릅니다. 왜 MutableList보다 List를 더 많이 사용하는지, 그리고 어떠한 부분이 다른 것인지는 variance 한정자의 안전성과 관련된 내용을 이해하면 알 수 있습니다.

 

 

 

List와 MutableList의 차이

  • Listout 한정자를 사용하여 공변성을 가진다. 즉, List<Dog>List<Animal>의 하위 타입이다.
open class Animal
class Dog : Animal()

val animals: List<Animal> = listOf(Dog()) // List<Dog>는 List<Animal>로 사용 가능

 

실제 코드

 

 

 

  • MutableList는 공변성을 갖지 않는다. 즉, MutableList<Dog>MutableList<Animal>의 하위 타입이 아니다.
val dogs: MutableList<Dog> = mutableListOf()
val animals: MutableList<Animal> = dogs // 컴파일 오류 발생

 

실제 코드

 

 

 

Covariant, Contravariant, Invariant, Type Erasure

 

 

반응형