Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- Perfect Watermark
- flink
- flink watermark
- Generic
- ingestion time
- event time
- MapReduce
- 불공변
- coroutines
- watermarks
- 공변
- Stream
- flink watermarks
- covariant
- 가변성
- contravariant
- Heuristic Watermark
- java
- Coroutine
- kotlin
- HDFS
- Perfect Watermarks
- processing time
- Heuristic Watermarks
- Hadoop
- apache flink
- Generics
- lambda
- watermark
Archives
- Today
- Total
mm Home
Kotlin - Generics 본문
Generic
Kotlin의 Generic은 Java의 Jeneric과 비슷한 점이 많으므로 Java - Generics 글을 참고하면 좋을듯 하다.
위 글을 통해 아래의 내용을 이해하면 된다.
Type Erasure
컴파일러가 하위 호환을 위해 Type Parameter 정보를 지운다. (런타임시에 타입 파라미터 정보를 알 수 없다)
공변 (Covariant)
A -> A' 일때, C -> C<A'>
*공변은 같은 기저타입에서 같은 방향으로 변한다.
반공변 (Contravariant)
A -> A' 일때, C <- C<A'>
*불공변은 공변의 반대. 다른 방향으로 변한다.
in variable
out variable
대략적인 사용은 아래와 같다. Java와 비슷하다.
interface List<T> {
fun test(i: Int): T
}
class A {
// 타입 파라미터 상한
fun <T : Number> List<T>.sum() : T
}
- 타입 파라미터를 반드시 정의해야 한다
- 타입 추론이 되는 경우 제외
- 구체화(reified) 할 수 있다
- 공변 (Covariant)
- java : ? extends T
- kotlin : in T
- 반공변 (Contravariant)
- java : ? super T
- kotlin : out T
- Wildcard 는 '*'
실체화 (Reification)
inline fun <reified T> readTo(t: T) {
println(T::class)
println(t)
}
//inline 키워드가 반드시 있어야 하는데, reified 키워드와 함께 있다면
//바이트코드를 복사하면서 구체화하기 떄문에 컴파일러가 타입을 알 수 있다. (빌드 시점에 타입 정보를 남기는 것)
readTo("sadasd")
//위의 코드를 사용하면 실제 컴파일이 되고 나면 아래와 같이 변경된다. 실제 inline 코드가 삽입될 때 Type까지 반영이 되는것.
println(String::class)
println("sadasd")
제약 사항
- 타입 파라미터 클래스의 인스턴스 생성
- 실체화하지 않은 타입을 파라미터로 받아 넘기기
- inline 함수가 아닌 타입 파라미터를 reified로 지정할 수 없다
가변성
공변
class C<in T> {
fun doPrint(t: T) {
println("do Something $t")
}
// 아래는 컴파일 에러. (공변 주었는데 write 하려고 하니까)
fun test2(): T? {
return null
}
}
fun test() {
//타입 파라미터가 Any 이므로 Any에 공변성을 가진다.
val c = C<Any>()
c.doPrint(A())
c.doPrint(B())
c.doPrint("ABC")
c.doPrint(123)
}
반공변
open class A {}
class B : A() {}
// T의 bound type은 지정해주지 않아도 된다. 타입 추론에 의해 자동적으로 타입을 알 수 있기 때문이다.
// 클래스 차원에서 사용가능한 타입파라미터를 제한할 수도 있다.
class D<out T>(val t: T) {
fun getter(): T {
return t;
}
// 아래는 컴파일 에러. (반공변 주었는데 read 하려고 하니까)
fun setter(t: T) {
}
}
fun test() {
// 타입 추론되어 타입 파라미터 생략
val aGetter = D(A()).getter(); //A
val bGetter = D(B()).getter(); //B
val sGetter = D("string").getter(); //String
val iGetter = D(123).getter(); //Int
}
// 아래처럼 쓸 수도 있다.
class D<out T : Int>(val t: T) {
fun toDouble(): Double {
return t.toDouble();
}
}
혹시 공변과 반공변을 같이 쓰고 싶다면 타입 파라미터를 하나 더 선언해야 한다.
class C<in T, out P>
'개발 > Kotlin' 카테고리의 다른 글
Kotlin Coroutines (0) | 2019.12.02 |
---|
Comments