Java 코드 중 일부를 Kotlin으로 변환 중이며 Kotlin 코드에 정의 된 인터페이스를 인스턴스화하는 방법을 잘 이해하지 못합니다. 예를 들어 인터페이스 (Java 코드로 정의)가 있습니다.
public interface MyInterface {
void onLocationMeasured(Location location);
}
그런 다음 Kotlin 코드 에서이 인터페이스를 인스턴스화합니다.
val myObj = new MyInterface { Log.d("...", "...") }
잘 작동합니다. 그러나 MyInterface를 Kotlin으로 변환 할 때 :
interface MyInterface {
fun onLocationMeasured(location: Location)
}
오류 메시지가 나타납니다. Interface MyListener does not have constructors
인스턴스화하려고하면 구문 이외의 다른 변경 사항이없는 것 같습니다. Kotlin에서 인터페이스의 작동 방식을 이해하지 못합니까?
답변
Java 코드는 SAM 변환 (람다를 단일 추상 메소드를 사용하여 인터페이스로 자동 변환)에 의존합니다. Kotlin에 정의 된 인터페이스 에는 현재 SAM 변환이 지원되지 않습니다 . 대신 인터페이스를 구현하는 익명 객체를 정의해야합니다.
val obj = object : MyInterface {
override fun onLocationMeasured(location: Location) { ... }
}
답변
가장 좋은 솔루션은 Java 인터페이스 대신 유형을 사용하는 것입니다.
typealias MyInterface = (Location) -> Unit
fun addLocationHandler(myInterface:MyInterface) {
}
다음과 같이 등록하십시오 :
val myObject = { location -> ...}
addLocationHandler(myObject)
또는 심지어 클리너
addLocationHandler { location -> ...}
다음과 같이 호출하십시오.
myInterface.invoke(location)
현재 3 가지 옵션은 다음과 같습니다.
- typealias (자바에서 호출하면 더러워 짐)
- kotlin 인터페이스 (kotlin에서 호출 할 때 더러워지고 개체를 만들어야 함) 이것은 IMO의 큰 단계입니다.
- 자바 인터페이스 (kotlin에서 호출 할 때 덜 지저분 해집니다. 람다는 앞에 인터페이스 이름이 필요하므로 객체가 필요하지 않으며 함수 괄호 규칙 외부에서 람다를 사용할 수 없습니다)
라이브러리를 Kotlin으로 변환 할 때 Kotlin의 Kotlin보다 Kotlin에서 Java를 호출하는 것이 더 깨끗했기 때문에 실제로 모든 인터페이스를 Java 코드로 남겨 두었습니다.
답변
다음과 같이 인터페이스에 액세스하십시오.
object : MyInterface {
override fun onSomething() { ... }
}
답변
다음 과 같은 Java 클래스 가있는 경우 :
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new RecyclerTouchListener.ClickListener()
{
//Your Code
}));
이 코드를 Java에서 Kotlin으로 다음 과 같이 변환해야합니다 .
override fun showJozList (list : List<ResponseGetJuzList.Parameter4>) {
adapter.addData(list)
jozlist_recycler.addOnItemTouchListener(RecyclerTouchListener(
activity ,
jozlist_recycler ,
object : RecyclerTouchListener.ClickListener
{
//Your Code
}))
Java 인터페이스 변환 :
new RecyclerTouchListener.ClickListener()
에 코 틀린 인터페이스 스타일 :
object : RecyclerTouchListener.ClickListener
답변
인터페이스가 클래스의 리스너 메소드 용인 경우 인터페이스 정의를 함수 유형으로 변경하십시오. 코드가 더 간결 해집니다. 다음을 참조하십시오.
리스너 정의를 포함하는 클래스
// A class
private var mLocationMeasuredListener = (location: Location) -> Unit = {}
var setOnLocationMeasuredListener(listener: (location: Location) -> Unit) {
mLocationMeasuredListener = listener
}
// somewhere in A class
mLocationMeasuredListener(location)
다른 수업
// B class
aClass.setOnLocationMeasuredListener { location ->
// your code
}
답변
class YourClass : YourInterface {
override fun getTest() = "test"
}
interface YourInterface {
fun getTest(): String
}
val objectYourClass: YourInterface = YourClass()
print(objectYourClass.getTest())