Extension이란 기존의 클래스나 데이터 타입에 새로운 기능을 추가하거나 확장하는 기술을 말한다.
주로 기능 확장, 인터페이스 구현, 라이브러리 확장, 안드로이드 프레임워크 확장, 안드로이드 스튜디오 플러그인 확장이 필요할 때 쓰인다고 한다..!
정말 코딩판은 틀에 박인 사고를 할 수 없는 환경인 것 같다.. 이거 라이브러리에서 주는건 좀 빈약해서 안될 것 같은데...는 안먹힌다. 만들어서 쓰면 되니까^^.. 부족하면 만들어서 먹으라구 extension이라는 기능도 제공하니까^^.. 개발자들.. 대다내..
무튼 이번 글에서는 캠프에서 배운 extension의 예시를 다시 살펴보고, 각각 쓰인 키워드에 대해서 조금 더 심도있게 이해해보는 내용을 작성해보려고 한다.
vararg pair: Pair<String, Any?>
라고 작성했다고 하면, 여러 개의 Pair<String, Any?>
인자를 받을 수 있게 된다.데이터를 특정 액티비티로 보낼 때 아래와 같이 작성한다.
private fun adapterOnClick(flower: Flower) { val intent = Intent(this, FlowerDetailActivity()::class.java) intent.putExtra(FlowerDetailActivity.EXTRA_FLOWER, flower.id) startActivity(intent) }
"만약" 액티비티 간 데이터 전환이 수십번 일어난다면? 매번 저 코드 3줄을 적어주는 것 보다는 extension으로 저 3줄에 대한 행위를 미리 정의해두고, 필요한 액티비티에서 꺼내다가 쓸 수 있도록 할 수 있다.
그럼 저 부분을 모든 액티비티에서 사용을 할 수 있게끔 extension으로 뽑아보자.
//intent.kt inline fun <reified T: Any> newIntent(context: Context) : Intent = Intent(context, T::class.java)
- 새로운 인텐트를 만드는 부분
- 함수의 이름은 newIntent이고, 저 이름으로 호출하여 사용하면 된다.
<reified T: Any>
로newIntent<여기에>
제네릭 타입이 들어올 수 있게 된다.- 인텐트를 생성할 때
T::class.java
로 해당하는 클래스를 가져올 수 있다.
//intent.kt inline fun <reified T : Any> Context.launchActivity(vararg pair: Pair<String, Any?>) { val intent = newIntent<T>(this) intent.putExtra(bundleOf(*pair)) startActivity(intent) }
- 만들어진 인텐트를 사용하여 데이터를 넘기고 액티비티를 시작하는 부분
- 위에서 만든 newIntent로 새로운 인텐트를 생성한다.
newIntent<T>(this)
부분을 보면 context 인자만 넣어서 넘기고 있는데,T
로 실행 중인 클래스를 알 수 있기 때문에 뒷 부분의 인자까지 작성하는 것은 의미가 없고 문법적으로 유효하지 않다고 한다.- vararg 키워드를 사용하여 여러 개의 Pair<String, Any?> 형태 인자가 들어올 수 있음에 대해 명시해둔다.
private fun adapterOnClick(flower: Flower) { val intent = Intent(this, FlowerDetailActivity()::class.java) intent.putExtra(FlowerDetailActivity.EXTRA_FLOWER, flower.id) startActivity(intent) }
private fun adapterOnClick(flower: Flower) { launchActivity<FlowerDetailActivity>(FlowerDetailActivity.EXTRA_FLOWER to flower.id) }
데이터를 보냈다면 받는 것도 필요할 것이다.
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val value = intent.extras?.getLong(EXTRA_FLOWER) val flower = value?.let { DataSource().getFlowerForId(it) } }
이 부분을 extension으로 뽑아보자.
//intent.kt inline fun <reified T : Any> Activity.extraNotNull(key : String, defalut : T? = null) = lazy { val value = intent?.extras?.getLong(key) requireNotNull(if(value is T) value else default) { key } }
- 데이터를 받아오는 부분
Activity.
하고 extraNotNull 이라는 함수명을 정의해주었으므로 이 함수는 액티비티 클래스의 확장 함수이고 액티비티 인스턴스를 통해 사용할 수 있다.key: String
는 데이터에서 값을 가져오기 위한 키 값을 의미한다.defult: T? = null
는 기본 값으로 사용할 수 있는 타입에 대한 정의이다. 만약 함수 호출 시 두 번째 매개변수 값이 비어있다면 기본 값으로 null이 사용된다.requirtNotNull(...) {}
은 제공된 값이 null이라면 exception을 발생 시키는데, () 안에if (value is T) value else default
가 들어가 있으므로 들어온 값이 제네릭 타입이면 해당 값을 반환, 그렇지 않다면 default를 반환한다.
- 결국 이 부분은 value가 제네릭 타입이 아니거나 null일 경우에는 exception이 발생되고, 그렇지 않다면 value를 그대로 반환한는 부분이다. (value를 검사하는 부분)
{ key }
를 두어, 예외가 발생하면 해당 키 값이 메세지로 출력되게 된다.- lazy 함수를 사용하므로 반드시 해당 블록 안에서 값이 초기화 되도록 한다(value)
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val value = intent.extras?.getLong(EXTRA_FLOWER) val flower = value?.let { DataSource().getFlowerForId(it) } }
private val flower by extraNotNull<Long>(EXTRA_FLOWER) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) DataSource().getFlowerForId(flower) }
- extension으로 정의해놓은 extraNotNull 확장 함수를 사용하여 flower를 선언한다.
[TIL-240409]