Uing? Uing!!

[내 맘대로 정리한 Kotlin] Functional Interaface: 오브젝트를 람다식으로 생성하기 본문

Kotlin

[내 맘대로 정리한 Kotlin] Functional Interaface: 오브젝트를 람다식으로 생성하기

Uing!! 2021. 7. 15. 22:42
반응형

View.setOnClickListener

안드로이드의 View.setOnClickListener는 아래처럼 OnClickListener라는 인터페이스를 받도록 설계되어 있다.

public void setOnClickListener(@Nullable OnClickListener l) {
  if (!isClickable()) {
  	setClickable(true);
  }
  getListenerInfo().mOnClickListener = l;
}

이 구조에 정확하게 맞추어서 코틀린 코드를 작성한다면 이렇게 될 것이다.

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

하지만 코틀린에서는 setOnClickListener를 이렇게 복잡하게 사용하지 않는다.

onClick 메소드의 내용만이 포함된 아래 람다식 표현이 더 익숙하다.

button.setOnClickListener {
	println("Clicked!")
}

이 간결한 표현식을 가능하게 해 주는 것이 바로 Functional(SAM) Interface covnersion이다.

 

 

Functional(SAM) Interface

SAM(Single Abstract Method)은 말 그대로 단 1개의 Abstract Method를 가졌다는 뜻이다.

앞서 언급한 View.setOnClickListener의 파라미터인 OnClickListener는 이렇게 생겼다.

public interface OnClickListener {
    void onClick(View v);
}

단 하나의 Abstract Method를 가진(SAM) 인터페이스임을 알 수 있다.

 

Functional(SAM) Interface covnersion

Kotlin은 이렇게 1개의 Abstract Method를 가진 자바 인터페이스를 간결한 람다식 형태로 생성할 수 있도록 지원한다.

 

그렇기 때문에 우리가 setOnClickListener { println("Clicked!") } 와 같이 람다식으로 줄여 표현해도 코틀린이 이를 잘 해석해서, 'OnClickListener의 단일 메소드인 onClick의 내용을 뜻하는구나!'라고 찰떡같이 알아듣고 컴파일해 주는 것이다.

 

하지만 인터페이스에 대한 SAM conversion에는 조건이 있었다.

람다식으로 표현될 인터페이스와 그 메소드가 Java로 작성되어 있어야 한다는 것이다.

 

따라서 우리가 코틀린으로 아래처럼 Calculator 인터페이스를 작성한다고 해도...

interface Calculator {
    fun calculate(a:Int, b:Int): Int
}

사용할 때에는 이를 람다식으로 표현할 수 없어 이렇게 정석적인 구현을 해야만 한다.

val adder = object: Calculator {
    override fun calculate(a: Int, b: Int): Int {
    	return a + b
    }
}

 

Functional(SAM) Interface in Kotlin

하지만 Kotlin 1.4부터는 코틀린으로 인터페이스를 작성하면서도 SAM conversion을 동작시키는 방법이 제공된다.

Functional Interface라는 새로운 형식의 Interface를 사용하는 것이다.

 

사용법은 간단하다. Interface 앞에 fun을 붙이면 된다.

* 단, SAM conversion을 위해 제공되는 Interface이므로 꼭 한 개의 abstract 메소드가 포함되어야 한다.

fun interface Calculator {
    fun calculate(a:Int, b:Int): Int
}

이제 위의 adder를 이전보다 훨씬 간결하게 생성할 수 있다.

val adder = Calculator { a, b -> a+b }
반응형
Comments