generic을 사용하여 코드를 작성할 때, generic type의 정보를 사용하고 싶은 경우가 있을 것이다.
아래 코드는 generic을 사용하여 파라미터의 타입을 확인하는 함수이다.
fun <T> isInstanceOf(obj: Any): Boolean {
println("check object(${obj::class}) is instance of ${T::class}")
return obj is T
}
하지만 generic은 compile 후 제거되기 때문에 위 코드와 같이 generic type을 직접적으로 사용하는 코드는 compile error를 낸다.
그래서 주로 아래와 같이 추가로 generic type과 같은 Class 타입의 파라미터를 받는 식으로 우회한다.
fun <T> isInstanceOf(obj: Any, type: Class<T>): Boolean {
println("check object(${obj::class}) is instance of ${type}")
return type.isInstance(obj)
}
inline과 reified keyword를 사용하면 파라미터를 추가로 받는 방식을 사용하지 않아도 된다.
inline fun <reified T> isInstanceOf(obj: Any): Boolean {
println("check object(${obj::class}) is instance of ${T::class}")
return obj is T
}
위와 같이 inline, reified keyword를 사용하면, 이 함수를 호출하는 쪽에서 호출 함수의 내용을 그대로 옮겨 generic으로 지정된 type의 class를 사용하여 기능을 실행한다.
코드로 살펴보자.
아래와 같이 main 함수에서 isInstanceOf 함수를 호출한다고 했을 때
import java.io.File
fun main() {
isInstanceOf<FileSystemException>(FileAlreadyExistsException(File("/path/to/file")))
}
inline fun <reified T> isInstanceOf(obj: Any): Boolean {
println("check object(${obj::class}) is instance of ${T::class}")
return obj is T
}
이 Kotlin 코드를 Java로 변환해보면 아래와 같다.
public final class ReifiedExampleKt {
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
public static final void main() {
Object obj$iv = new FileAlreadyExistsException(new File("/path/to/file"), (File)null, (String)null, 6, (DefaultConstructorMarker)null);
String var2 = "check object(" + Reflection.getOrCreateKotlinClass(obj$iv.getClass()) + ") is instance of " + Reflection.getOrCreateKotlinClass(FileSystemException.class);
System.out.println(var2);
boolean var10000 = obj$iv instanceof FileSystemException;
}
// $FF: synthetic method
public static final boolean isInstanceOf(Object obj) {
StringBuilder var10000 = (new StringBuilder()).append("check object(").append(Reflection.getOrCreateKotlinClass(obj.getClass())).append(") is instance of ");
String var2 = var10000.append(Reflection.getOrCreateKotlinClass(Object.class)).toString();
System.out.println(var2);
return obj instanceof Object;
}
}
main 메서드가 isInstanceOf 메서드와 기능적으로 동일한 코드를 갖고 있고,
generic으로 명시된 FileSystemException을 사용하여 기능을 실행하는 것을 볼 수 있다.
OOP를 사용하면 함수 레벨에서 generic을 쓰기보다는 주로 class 레벨에서 generic을 주로 사용하게 되는데,
reified는 class 레벨에서 사용할 수 없기 때문에 내가 이를 실제로 사용할만한 부분이 있을까 싶다 🤔
'Java & Kotlin > Kotlin' 카테고리의 다른 글
[MockK] mock 객체가 호출되지 않았음을 검증하기 (1) | 2022.10.21 |
---|---|
JPA entity의 VO로 Kotlin value class 사용하기 (3) | 2022.06.01 |
[MockK] 메서드 호출 순서 검증하기 (0) | 2022.04.15 |
[MockK] 인자 값 그대로 리턴하기 (0) | 2022.04.14 |
observable, vetoable를 통한 프로퍼티 변경 감지 (0) | 2021.11.06 |
댓글