제네릭과 배열 (2/3)
Do it! 코틀린 프로그래밍 [셋째마당, 코틀린 표준 라이브러리의 활용] 학습
1-3. 자료형 제한하기
- 콜론(:)과 자료형을 기입하여 형식 매개변수의 자료형을 제한
📌 클래스에서 형식 매개변수의 자료형 제한
class Calc<T: Number> {
fun plus(arg1: T, arg2: T): Double {
return arg1.toDouble() + arg2.toDouble()
}
}
fun main() {
val calc = Calc<Int>()
val calc2 = Clac<String>() // !오류!
}
-> 형식 매개변수 T를 Number형으로만 제한해두었기 때문에 객체를 생성할 때 String과 같이 Number형이 아닌 자료형이 지정되면 오류 발생
📌 함수에서 형식 매개변수의 자료형 제한
fun <T : Number> addLimit(a: T, b: T, op: (T, T) -> T): T {
return op(a, b)
}
val result = addLimit("abc", "def", { a, b -> a + b }) // !오류!
-> 함수 이름 앞에 형식 매개변수를 Number형으로만 제한하여 문자열 처리 불가
📌 다수 조건의 형식 매개변수 제한
where
키워드를 통해 지정된 제한을 모두 포함하는 경우만 허용하도록
⬇️ 클래스에서 where 사용
interface InterfaceA
interface InterfaceB
class HandlerA: InterfaceA, InterfaceB
class HandlerB: InterfaceA
class ClassA<T> where T:InterfaceA, T:InterfaceB
fun main() {
val obj1 = ClassA<HandlerA>()
val obj2 = ClassA<HandlerB>() // !오류!
}
-> InterfaceA만 구현하는 HandlerB는 where범위에 들어갈 수 없음
⬇️ 함수에서 where 사용
fun <T> myMax(a: T, b: T): T where T:Number, T:Comparable<T> {
return if (a > b) a else b
}
-> a, b에 들어갈 자료형을 숫자형과 비교형으로 한정
1-4. 상·하위 형식의 가변성
- 가변성(Variance) : 형식 매개변수가 클래스 계층에 영향을 주는것
📌 클래스와 자료형
📌 가변성의 3가지 유형
용어 | 의미 |
---|---|
공변성(Covariance) | T'가 T의 하위 자료형이면, C<T'> 는 C<T> 의 하위 자료형이다. 생산자 입장의 out 성질 |
반공변성(Contravariance) | T'가 T의 하위 자료형이면, C<T> 는 C<T'> 의 하위 자료형이다. 생산자 입장의 in 성질 |
무변성(Invariance) | C<T'> 와 C<T> 는 아무 관계가 없다. 생산자 + 소비자 |
📌 무변성 (Invariance)
- 형식 매개변수에 공변성이나 반공변성을 따로 지정하지 않으면 무변성으로 제네릭 클래스가 선언됨
class Box<T>(val size: Int)
fun main() {
val anys: Box<Any> = Box<Int>(10) // !오류! 자료형 불일치
val nothings: Box<Nothing> = Box<Int>(20) // !오류! 자료형 불일치
}
-> 제네릭 클래스가 무변성으로 선언되었을 경우, 클래스의 상하관계를 올바르게 따졌어도 자료형 불일치 오류가 발생
📌 공변성 (Covariance)
- 형식 매개변수의 상하 자료형 관계가 성립하고, 그 관계가 그대로 인스턴스 자료형 관계로 이어지는 경우
Int
가Any
의 하위 자료형일 때 형식 매개변수 T에 대해 공변적이라고 함- 형식 매개변수를 갖는 프로퍼티는 val만 허용
- var를 사용하려면 private으로 지정해야함
out
키워드 사용
// 공변성 선언
class Box<out T>(val size: Int)
fun main() {
val anys: Box<Any> = Box<Int>(10) // 객체 생성 가능
val nothings: Box<Nothing> = Box<Int>(20) // !오류! 자료형 불일치
}
-> Any의 하위 클래스인 Int는 공변성을 가지므로 자료형 할당 가능
-> Nothing은 Int의 하위 자료형이 아니므로 오류 발생
📌 반공변성 (Contravariance)
- 자료형의 상하관계가 반대가 되어 인스턴스의 자료형이 상위 자료형이 됨
in
키워드 사용
// 반공변성 선언
class Box<in T>(val size: Int)
fun main() {
val anys: Box<Any> = Box<Int>(10) // !오류! 자료형 불일치
val nothings: Box<Nothing> = Box<Int>(20) // 객체 생성 가능
}
-> Box<Noting>
자료형의 상위 자료형이 Box<Int>
이므로 객체를 생성할 수 있음
1-5. 자료형 프로젝션
📌 선언 지점 변성(declaration-site variance)
- 클래스를 선언하면서 클래스 자체에 가변성을 지정하는 방식
- 클래스를 사용하는 장소에서는 따로 자료형을 지정해 줄 필요 없음
📌 사용 지점 변성(use-site variance)
- 메서드 배개변수에서 또는 제네릭 클래스를 생성할 때와 같이 사용 위치에서 가변성을 지정하는 방식
- 형식 매개변수가 있는 자료형을 사용할 때마다 하위 자료형이나 상위 자료형 중 어떤 자료형으로 대체할 수 있는지 명시 필요
📌 스타 프로젝션
- in/out 을 정하지 않고 스타(*)를 통해 지정하는 방법
- 구체적으로 자료형이 결정되고 난 후 그 자료형과 하위 자료형의 요소만 담을 수 있도록 제한
class InOutTest<in T, out U>(t: T, u: U) {
val propT: T = t // !오류! T는 in 위치이기 때문에, out 위치에 사용 불가
val propU: U = u // U는 out 위치로 가능
fun func1(u: U) // !오류! U는 out 위치이기 때문에 in 위치에 사용 불가
fun func2(t: T) { } // T는 in위치에 사용됨
}
fun startTestFunc(v: InOutTest<*, *>) {
v.func2(1) // !오류! Nothing으로 인자를 처리
print(v.propU)
}
-> in으로 정의되어 있는 형식 매개변수를 로 받으면 in Nothing으로 간주
-> out으로 정의되어 있는 형식 매배경수를 로 받으면 out Any?로 간주
1-6. reified 자료형
fun <T> myGenericFun(c: Class<T>)
- T자료형은 자바처럼 실행 시간에 삭제되기 때문에 T자체에 그대로 접근 불가능
<T>
처럼 결정되지 않은 제네릭 자료형은 컴파일 시간에는 접근 가능하나 함수 내부에서 사용하려면c: Class<T>
처럼 함수의 매개변수에 넣어 지정해야만 실행시간에 사라지지 않고 접근 가능
inline fun <reified T> myGenericFun()
reified
로 형식 매개변수 T를 지정하면 실행 시간에 접근 가능- 단
reified
자료형은 인라인 함수에서만 사용 할 수 있음
fun main() {
val result = getType<Int>(10)
println("result = $result")
}
inline fun <reified T> getType(value: Int): T {
println(T::class) // T는 실행 시간에 삭제되지 않고 사용 가능
println(T::class.java)
return when(T::class) { // 받아들인 제네릭 자료형에 따라 반환
Float::class -> value.toFloat() as T
Int::class -> value as T
else -> throw IllegalStateException("${T::class} is not supported!")
}
}
Author And Source
이 문제에 관하여(제네릭과 배열 (2/3)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@zzangdd/제네릭과-배열-23저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)