본문 바로가기
Kotlin

Kotlin - 람다식, SAM변환

by 봄석 2019. 1. 3.

Kotlin - 람다식, SAM변환


람다식

코틀린은 자바 8과 같이 람다식을 지원합니다. 람다식은 하나의 함수를 표현하는 방법으로

익명 클래스나 익명 함수를 간결하게 표현할 수 있어서 매우 유용합니다.


람다식은 코드를 간결하게 해주는 장점이 있지만 디버깅이 어렵고 남발할 경우 오히려 코드의 가독성이 떨어져 주의해야 합니다.


먼저 두 인수를 받아서 더해주는 add() 메소드입니다.

fun add(x:Int,y:Int):Int{
    return x+y

}



위의 코드는 아래처럼 표현할 수 있습니다. 반환 자료형을 생략하고 블록{}과 return을 생략할 수 있습니다.

fun add(x:Int,y:Int)=x+y


또한 아래처럼 표현할 수도 있습니다. 코틀린의 람다식은 다음과 같이 항상 중괄호로 둘러싸여 있습니다. 내용으로는 인수 목록을 나열하고 - >이후에 본문이 위치합니다. 람다식을 변수에 저장할 수 있고 이러한 변수는 일반함수처럼 사용 가능합니다.

//{인수1: 타입1, 인수2: 타입2 -> 본문}
var add= {x:Int,y:Int->x+y}
 

println(add(2,5)) //7




SAM 변환

코틀린에서는 추상 메소드 하나를 인수로 사용할 때는 함수를 인수로 전달하면 편합니다.

자바로 작성된 메소드가 하나인 인터페이스를 구현할 때는 대신 함수를 작성할 수 있습니다.

이를 SAM(Single Abstract Method) 변환 이라 합니다.


SAM 변환의 예를 안드로이드에서 들어보겠습니다. 안드로이드에서는 버튼의 클릭 이벤트를 구현할 때 onClick() 추상 메소드만을 가지는 View.OnClickListener 인터페이스를 구현합니다.


아래는 안드로이드에서 버튼에 클릭 이벤트 리스너를 구현하는 코드를 일반적인 익명 클래스를 작성하듯이 작성한 코드입니다. 여기서 View.OnClickListener 인터페이스에는 onClick() 추상 메소드가 하나 있기 때문에 onClick() 메소드를 오버라이드 하고 있습니다.

button.setOnClickListener(object : : View.OnClickListener {
    override fun onClick(v: View?){
 
    }
})


구현하는 인터페이스에 구현하는 메소드가 하나뿐일때는 이를 람다식으로 변경할 수 있습니다.

다음 코드는 람다식으로변경되어 코드가 줄었지만 괄호도 중첩되어있고 기호도 많아 복잡해보입니다.

button.setOnClickListener({ v: View? ->
    //클릭시 처리
})


메소드 호출 시 맨 뒤에 전달되는 인수가 람다식인 경우에는 람다식을 괄호 밖으로 뺄 수 있습니다. 위의 코드는 하나의 인수만 있고 람다식이 전달되었기 때문에 마지막 인수라고 볼 수 있습니다.


아래와같이 변경가능합니다

button.setOnClickListener(){v:View?->
    //클릭시 
}



그리고 람다가 어떤 메소드의 유일한 인수인 경우에는 메소드의 괄호를 생략할 수 있습니다

아래처럼

button.setOnClickListener{v:View?->
    //클릭시 

}



컴파일러가 자료형을 추론하는 경우에는 자료형도 아래처럼 생략할 수 있습니다.

button.setOnClickListener{v->
    //클릭시 처리

}



만약 클릭시에 어떤 코드를 작성했는데 v 인수를 사용하지 않는다면 v라는 이름은 _기호로 대치할 수 있습니다. 인수가 많은 경우에 꼭 사용하는 인수 이외에는 _기호로 변경하여 애초에 잘못 사용하는 것을 방지할 수도 있습니다. 이러한 방식은 다른 함수형 언어에서도 적용되는 함수형 언어의 특징 중 하나입니다.

button.setOnClickListener{_->
    //클릭시 처리

}


그리고 람다식에서 인수가 하나인 경우에는 이를 아예 생략하고 람다 블록 내에서 인수를 it로 접근할 수 있습니다.

아래 코드에서 it은 View? 타입의 v인수를 가르킵니다.

button.setOnClickListener{
    it.visibility=View.GONE

}


위의 7가지 형태는 모두 같은 결과를 나타내지만 마지막 코드가 가장 읽기 쉽습니다


중요한 것은 SAM 변환은 자바에서 작성한 인터페이스일 때만 동작한다는 겁니다. 코틀린에서는 인터페이스 대신에 함수를 사용하는 것이 좋습니다.

댓글