[코틀린] 람다식의 매개변수

에짱·2021년 8월 23일
0
post-thumbnail
post-custom-banner

람다식에 매개변수가 없는 경우

fun main() {
	noParam({"Hello World!" }) //Hello World!
	noParam{"Hello World!"} //Hello World!
}

fun noParam(out : () -> String) = println(out())

noParam 매개변수 out은 람다식 1개를 가지고 있는데, 이 람다식에 매개변수가 없으므로 main 함수에서 인자를 넣을 때, -> 기호가 사용되지 않았습니다.
그리고 이런 경우 소괄호를 생략할 수 있습니다.

람다식에 매개변수가 1개인 경우

fun main() {
	oneParam({ a -> "Hello World! $a"}) //Hello World! OneParam
	oneParam{ a -> "Hello World! $a"} //Hello World! OneParam
	oneParam{ "Hello World! $it"} //Hello World! OneParam
}

fun oneParam(out : (String) -> String) {
	println(out("OneParam"))

매개변수가 1개인 람다식을 표현하고자 할 경우, 화살표를 생략하고 it 으로 대체할 수 있습니다.

람다식 매개변수가 2개 이상인 경우

fun main() {
	moreParam{ a, b -> "Hello World! $a $b" } 
    	//Hello World! OneParam TwoParam
}

fun moreParam(out : (String, String) -> String) {
	println(out("OneParam", "TwoParam"))
}

람다식의 매개변수가 2개 이상인 경우는 it 으로 대체할 수 없습니다.

특정 매개변수를 사용하고 싶지 않은 경우

moreParam{ _, b -> "Hello World! $b" } 
//첫 번째 문자열은 사용하지 않고 생략

이름 대신 언더스코어(_)로 대체하면 됩니다.

일반 매개변수와 람다식 매개변수 같이 사용하기

사실 람다 시리즈는 이 부분을 위해 작성했다고 봐도 과언이 아닙니다😅 제가 오픈 소스 코드에서 이 부분이 적용된 코드를 보다가 이해가 안 되서 람다 공부를 시작했거든요🤓

fun main() {
	withArgs("Arg1", "Arg2", { a, b -> "Hello World! $a $b" })
	withArgs("Arg1", "Arg2") { a, b -> "Hello World! $a $b" }
	//withArgs 함수 마지막 인자가 람다식인 경우, 소괄호 바깥으로 분리 가능
}

fun withArgs(a: String, b: String, out : (String, String) -> String) {
	println(out(a, b))
}

람다식이 짧으면 소괄호 안에 인자를 모두 전달할 수 있지만, 길어지면 읽기가 어렵기 때문에 main 함수의 두 번째 코드처럼 람다식만 소괄호 바깥으로 뺄 수 있습니다. 바깥으로 빠진 람다식을 withArgs 함수의 처리 부분으로 오해할 수 있으니 조심하세요~!🧐

하지만 이렇게 바깥으로 빼서 간략화하려면 람다식 매개변수가 마지막 인자 위치에 있어야 한다는 규칙이 있습니다!!!

안드로이드 adapter click event 예시 코드

안드로이드 개발할 때, adapter 는 반드시 한 번 이상은 구현을 해야 하는 존재인데요, adapter 를 개발할 때 자연스럽게 들어가는 녀석이 클릭이벤트 처리입니다.

클릭이벤트 처리를 구현하는 방법은 정말 다양한데, 오늘 배운 람다식으로 구현된 코드를 살펴보도록 하겠습니다.

아래는 adapter 에 data와 click event 처리 부분을 람다식으로 넣는 mainActivity의 코드 부분입니다.

MainActivity.kt

...
 adapter.setSearchResultList(dataList) {
            Toast.makeText(
                this,
                "빌딩이름 : ${it.buildingName}, 주소: ${it.fullAddress}, 위도/경도: ${it.locationLatLng}",
                Toast.LENGTH_SHORT
            ).show()
            startActivity(Intent(this, MapActivity::class.java).apply {
                putExtra(SEARCH_RESULT_EXTRA_KEY, it)
            })
        }

사용자가 지역을 검색하면 주소를 recyclerview 로 보여주고 그 recyclerview 의 adapter 가 아래와 같습니다.

SearchRVAdapter.kt

class SearchRvAdapter : RecyclerView.Adapter<SearchRvAdapter.SearchResultViewHolder>() {

    private var searchResultList: List<SearchResultEntity> = listOf()
    private lateinit var searchResultClickListener: (SearchResultEntity) -> Unit

    class SearchResultViewHolder(
        val binding: ItemSearchResultBinding,
        val searchResultClickListener: (SearchResultEntity) -> Unit
    ) : RecyclerView.ViewHolder(binding.root) {

        fun bindData(data: SearchResultEntity) = with(binding) {
            tvTitle.text = data.buildingName
            tvSubtitle.text = data.fullAddress
        }

        fun bindView(data: SearchResultEntity) {
            binding.root.setOnClickListener {
                searchResultClickListener(data)
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchResultViewHolder {
        val view =
            ItemSearchResultBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return SearchResultViewHolder(view, searchResultClickListener)
    }

    override fun onBindViewHolder(holder: SearchResultViewHolder, position: Int) {
        holder.bindData(searchResultList[position])
        holder.bindView(searchResultList[position])
    }

    override fun getItemCount(): Int = searchResultList.size

    fun setSearchResultList(
        searchResultList: List<SearchResultEntity>,
        searchResultClickListener: (SearchResultEntity) -> Unit
    ) {
        this.searchResultList = searchResultList
        this.searchResultClickListener = searchResultClickListener
        notifyDataSetChanged()
    }
}

adapter 의 멤버함수 setSearchResultList를 보면 매개변수가 일반 매개변수 하나와 람다식 매개변수 하나로 구성되어 있는 것을 알 수 있고, 람다식 매개변수가 마지막에 위치하고 있습니다. 따라서 mainActivity 에서 (dataList) 는 첫 번째 인자, { Toast.makeText...} 는 두 번째 람다식 인자에 대응되는 것입니다.

{Toast.makeText...}를 보면 중간에 it이 사용된 것을 볼 수 있는데요, 이는 람다식의 매개변수가 1개라는 뜻이죠. setSearchResultList 함수를 보면 매개변수가 (SearchResultEntity) 하나라는 것을 알 수 있습니다.

인자로 들어온 람다식은 adapter class의 searchResultClickListener 에 대입됩니다.
SearchResultViewHolder 내부의 bindView 함수를 보면, 클릭 이벤트 발생시, searchResultClickListener 변수를 함수처럼 사용해서 data 를 인자로 넣어주는 것을 알 수 있습니다. 이 data 는 람다식의 매개변수 SearchResultEntity 에 들어가고 결과적으로, 클릭하면 data에 따른 toast 메세지를 띄우게 되는 것이죠.

정리

지금까지 람다식의 매개변수를 개수에 따라서(목차1~3), 그리고 람다식 매개변수를 갖는 함수(목차4)에 대해서 살펴보았고, 추가적으로 안드로이드 어뎁터에서 클릭이벤트를 구현할 때 적용할 수 있다는 것을 예시 코드로 확인해보았습니다. 말이 조금 헷갈릴 수 있는데요.. 😅 예시 코드를 보면서 천천히 이해하시면 좋겠습니다!

profile
지금 여기. Here and Now
post-custom-banner

0개의 댓글