여러 타입에 대해 작동할 수 있는 컴포넌트인
파라미터화한 타입을 만드는 제네릭스
오늘은 여러 가지 클래스에 적합한/관계있는 제네릭스에 대해 학습하는 아톰이다.
[ 제네릭스 ]
제네릭스
: 클래스나 함수를 작성할 때 타입 제약을 느슨하게 해 표현력을 최대로 제공
: 제네릭 타입 정의를 위해 클래스 이름 뒤에, 내부에 하나 이상의 제네릭 플레이스 홀더가 들어있는 부등호(<>)를 추가
import atomictest.eq
class GenericHolder<T> (private val value: T){ // T 타입의 객체를 저장 및 반환
fun getValue(): T = value
}
fun main() {
val hi = GenericHolder(Automobile("Ford"))
val a: Automobile = hi.getValue() // 결과가 자동으로 올바른 타입으로 저장
a eq "Automobile(brand=Ford)"
val h2 = GenericHolder(1)
val i : Int = h2.getValue() // 결과가 자동으로 올바른 타입으로 저장
i eq 1
val h3 = GenericHolder("Chartreuse")
val s: String = h3.getValue() // 결과가 자동으로 올바른 타입으로 저장
s eq "Chartreuse"
}
: T라는 플레이스 홀더는 지금은 알 수 없는 어떤 타입을 대신하며, 제네릭 클래스 안에서 일반 타입처럼 사용
[ Any ]
Any
: 코틀린에서의 유니버설 타입
: 유니버설 타입은 모든 타입의 부모 타입으로, 모든 타입의 인자를 허용
: 위의 예제에서 T 대신 Any를 사용하는 것도 가능함
: 간단한 경우 작동하지만, 구체적인 타입이 필요해질 경우 제대로 작동하지 않는 경우가 존재 (아래 예시 참고)
import atomictest.eq
class AnyHolder(private val value: Any) {
fun getValue(): Any = value
}
class Dog {
fun bark() = "Ruff!"
}
fun main() {
val holder = AnyHolder(DogO)
val any = holder.getValue()
// any.bark() - 구체적이지 않기 때문에 컴파일 불가능
// 아래와 같이 한 번 거쳐서 구체적인 타입 명시가 필요
val genericHolder = GenericHolder(Dog())
val dog = genericHolder.getValue()
dog.bark() eq "Ruff!"
}
[ 제네릭 함수]
제네릭 함수
: 정의를 위해 부등호로 둘러싼 제네릭 타입 파라미터를 함수 이름 앞에 붙임
: 확장 함수를 사용하기 위해서는 수신 객체 앞에 제네릭 명세(괄호로 둘러싼 타입 파라미터 목록)를 위치시켜야 함
import atomictest.eq
// 제네릭 함수
fun <T> identity(arg: T): T = arg
// 확장 함수
fun <T> List<T>,first(): T {
if (isEmpty())
throw NoSuchElementException("Empty List")
return this[0]
}
fun <T> List<T>.firstOrNull(): T?=
if (isEmpty()) null else this[0]
fun main() {
// 제네릭 함수 예시
identity("Yellow") eq "Yellow"
identity(1) eq 1
val d: Dog = identity(Dog())
d.bark() eq "Ruff!"
// 확장 함수 예시
listOf(1, 2Z 3).first() eq 1
vali: Int? = listOf(1 z 2, 3) .firstOrNul() // 식별자 타입에 ?가 필요
i eq 1
val s: String? = listOf<String>().firstOrNul() // 식별자 타입에 ?가 필요
s eq null
}
: 식별자 타입에 ?가 없을 경우 '널이 될 수 없는 타입을 기대하며, 널이 될 수 없는 타입이 와야 한다'는 오류가 발생하게 됨
'공부 자료 > 코틀린[Kotlin]' 카테고리의 다른 글
[Atomic 43] break와 continue (3) | 2024.02.21 |
---|---|
[Atomic 42] 확장 프로퍼티 (0) | 2024.02.21 |
[Atomic 40] 확장 함수와 널이 될 수 있는 타입(라이브러리 함수) (0) | 2024.02.20 |
[Atomic 39] 널 아님 단언 (0) | 2024.02.20 |
[Atomic 38] 안전한 호출과 엘비스 연산자 (0) | 2024.02.13 |