일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- todofication
- 안드로이드 클린 아키텍쳐
- java.lang.OutOfMemoryError: Java heap space
- compileKotlin FAILED
- andorid
- recyclerview
- RxJava
- nvidia-docker
- RX
- 타이머앱
- 특가게시판
- 뷰 상태 저장
- 카드 내역 공유 앱
- List
- 작성
- 특가촌
- 대학톡
- android clean architecture
- Android
- 카드내역 공유
- 안드로이드
- kotlin
- Koin
- fragment
- 뷰 상태복구
- Quickly
- onViewCreated
- 특가알람
- 올인원타이머
- moveToState
- Today
- Total
seoft
[kotlin/android] 리플랙션을 사용해 KClass로 인스터스 생성하기 본문
[요약]
코틀린에서 리플랙션을 사용하면 KClass를 가지고 있다가 필요시 인스턴스화 할 수 있다.
다음과 같은 상황이 있다고 가정해보자(억지지만)
sealed class Animal(open val age: Int) { | |
data class Dog(override val age: Int) : Animal(age) | |
data class Cat(override val age: Int) : Animal(age) | |
data class Bird(override val age: Int) : Animal(age) | |
} |
먼저 서버에서도 받아오고 다른대서도 공통으로 사용되는 데이터 클래스가 존재한다.
enum class AnimalType( | |
val selectText: String, | |
val hungryText: String | |
) { | |
DogType("개를 선택했어요", "멍멍이는 배고파요"), | |
CatType("고양이를 선택했어요", "야옹이는 배고파요"), | |
BirdType("새를 선택했어요", "구구는 배고파요") | |
} |
또한 특정 페이지에 공통으로 사용되는 프로퍼티들이 있어 타입별 enum으로 정의하여 사용한다.
공통으로 사용하는 페이지가 있고, 진입시 타입에 따라 알맞은 인스터스를 생성해 사용해야 한다.
if (animalType == AnimalType.DogType) { | |
animal = Animal.Dog(age) | |
} else if (animalType == AnimalType.CatType) { | |
animal = Animal.Cat(age) | |
} else if (animalType == AnimalType.BirdType) { | |
animal = Animal.Bird(age) | |
} | |
// 중략... | |
onSelect { | |
println("${animal.age}살의 ${animalType.selectText}") | |
} | |
onHungry { | |
println("${animal.age}살의 ${animalType.hungryText}") | |
} |
enum을 통해 분기를 타지 않고 사용할 수 있지만,
어쩔수 없이 인스터스 생성은 다음과같이 타입별로 if분기를 타서 정의한다.
지금은 분기가 크게 많지 않지만 타입이 3개가아니라 10개, 100개 if분기가 늘어날것이다 .
이런 분기를 없애기위해 enum으로 다른 분기는 제외시켰으나
인스턴스 생성은 따로 해줘야되는게 좀 비효율적인거같아 리서치 해본 결과,
다음처럼 사용할 수 있다.
implementation 'org.jetbrains.kotlin:kotlin-reflect:1.3.72' |
inline fun <reified T : Any> createObject(clazz: KClass<out T>): T { | |
return clazz.java.newInstance() | |
} | |
inline fun <reified T : Any> createObject(clazz: KClass<out T>, vararg args: Any?): T { | |
return clazz.constructors.first().call(*args) | |
} |
우선 클래스를 인스턴스화하는 코드를 준비한다. (디펜던시 추가 + 유틸함수 준비)
Before :
enum class AnimalType( | |
val selectText: String, | |
val hungryText: String | |
) { | |
DogType("개를 선택했어요", "멍멍이는 배고파요"), | |
CatType("고양이를 선택했어요", "야옹이는 배고파요"), | |
BirdType("새를 선택했어요", "구구는 배고파요") | |
} |
After :
enum class AnimalType2( | |
val createClass: KClass<out Animal>, | |
val selectText: String, | |
val hungryText: String | |
) { | |
DogType(Animal.Dog::class, "개를 선택했어요", "멍멍이는 배고파요"), | |
CatType(Animal.Cat::class, "고양이를 선택했어요", "야옹이는 배고파요"), | |
BirdType(Animal.Bird::class, "새를 선택했어요", "구구는 배고파요") | |
} |
그리고 enum타입에 Animal의 하위 kclass를 추가로 받는다.
Before :
if (animalType == AnimalType.DogType) { | |
animal = Animal.Dog(age) | |
} else if (animalType == AnimalType.CatType) { | |
animal = Animal.Cat(age) | |
} else if (animalType == AnimalType.BirdType) { | |
animal = Animal.Bird(age) | |
} | |
// 중략... | |
onSelect { | |
println("${animal.age}살의 ${animalType.selectText}") | |
} | |
onHungry { | |
println("${animal.age}살의 ${animalType.hungryText}") | |
} |
After :
animal = createObject(animalType2.createClass, age) | |
// 중략... | |
onSelect { | |
println("${animal.age}살의 ${animalType2.selectText}") | |
} | |
onHungry { | |
println("${animal.age}살의 ${animalType2.hungryText}") | |
} |
마지막으로 다음 코드를 통해 enum타입에서 사전에 받은 kclass로 인스터스를 생성한다.
[결론]
리플랙션을 사용하면 KClass를 인스턴스화 할 수 있고
사용성 중 하나로 공통화된 모듈에서 분기를 최소화하고 enum으로만 관리하고자 할때 사용 할 수있다.
하지만 적지않은 kotlin-reflect.jar 의 용량, 리플랙션의 위험성, 비교적 성능저하 을 고려한다면 if분기로 가는 방향도 알맞을 수 있다.
상황에 맞게 사용하면 좋게 쓰일 수 있을 것 같다.
[참조]
stackoverflow.com/questions/47499838/how-to-pass-vararg-to-a-varag-function-or-constructor-in-kotlin
How to Pass vararg to a varag function or constructor in Kotlin?
Kotlin does not allow my subclass to pass vararg to my super class constuctor Here is my Operation class: package br.com.xp.operation import java.util.ArrayList abstract class Operation(vararg v...
stackoverflow.com
'android' 카테고리의 다른 글
[Rx,Kotlin] zip 연산자로 복수개(list)의 single 결합 (0) | 2020.07.13 |
---|---|
[Android, Glide] url로 부터 image file 저장하기 (0) | 2020.06.26 |
LiveDataUtil : LiveData 리스트 형식 관리 (0) | 2020.05.16 |
[java, kotlin] 상속관계 리스트 json타입, 객체타입 전환 (with gson) (0) | 2020.05.16 |
Retrofit으로 Body 비어있는 Response 받기 (0) | 2020.04.23 |