Kotlin: Interface… yapıcıları yok


138

Java kodumun bir kısmını Kotlin'e dönüştürüyorum ve Kotlin kodunda tanımlanan arayüzlerin nasıl oluşturulacağını tam olarak anlamıyorum. Örnek olarak, bir arayüz var (Java kodunda tanımlanmıştır):

public interface MyInterface {
    void onLocationMeasured(Location location);
}

Ve daha sonra Kotlin kodumda bu arayüzü somutlaştırıyorum:

val myObj = new MyInterface { Log.d("...", "...") }

ve iyi çalışıyor. Ancak, MyInterface'i Kotlin'e dönüştürdüğümde:

interface MyInterface {
    fun onLocationMeasured(location: Location)
}

Bir hata mesajı alıyorum: Interface MyListener does not have constructorssomutlaştırmaya çalıştığımda - bana sözdizimi dışında hiçbir şeyin değişmediği görülüyor. Kotlin'de arayüzlerin nasıl çalıştığını yanlış anlıyor muyum?

Yanıtlar:


226

Java kodunuz SAM dönüşümüne dayanır - lambda'nın tek bir soyut yöntemle otomatik olarak bir arayüze dönüştürülmesi. SAM dönüşümü şu anda Kotlin'de tanımlanan arayüzler için desteklenmemektedir . Bunun yerine, arabirimi uygulayan anonim bir nesne tanımlamanız gerekir:

val obj = object : MyInterface {
    override fun onLocationMeasured(location: Location) { ... }
}

14
Çok teşekkürler. Gönderdiğiniz bağlantıdan, mümkünse Location -> Unittek yöntemli arayüzler yerine fonksiyonel tiplerin (örneğin ) kullanılmasının tercih edildiğini anlıyorum - bu doğru mu?
Aleph Aleph

4
Doğru. Mümkün olan her yerde fonksiyonel tip kullanmalısınız.
Yoav Sternberg

Ancak benim durumumda arayüzün (SurfaceTextureListener) birden fazla yöntemi vardı.
Tash Pemhiwa

Çok teşekkürler. Bu cevabın daha fazla beğeni veya özel bir işareti olmalı, çünkü çok yararlı bilgiler ve maalesef bazı öğrenciler Kotlin'i makalelerle veya SAM konusuna baktıklarında "Kotlin in Action" ile öğrendiklerinde çok karışabilirler.
TT_W

"Kotlin in Action" dan, evet, Java'nın SAM parametresinde kısaltmak ve daha temiz kod için lambda kullanabilirsiniz, ancak Kotlin'in SAM'ı değil, işlev türü Kotlin'deki ilk sınıftır, bu yüzden SAM, Kotlin için bir anlam ifade etmez, tipealias ile fonksiyon türü daha Kotlin tarzı.
vg0x00

17

En iyi çözüm, Java arayüzünüzün yerinde bir daktilo kullanmaktır.

typealias MyInterface = (Location) -> Unit

fun addLocationHandler(myInterface:MyInterface) {

}

Bu şekilde kaydedin:

val myObject = { location -> ...}
addLocationHandler(myObject)

hatta daha temiz

addLocationHandler { location -> ...}

Şöyle çağırın:

myInterface.invoke(location)

Mevcut 3 seçenek şöyledir:

  • typealias (java denildiğinde dağınık)
  • kotlin arayüzü (kotlin'den çağrıldığında dağınık; bir nesne oluşturmanız gerekir) Bu IMO için büyük bir adım.
  • java arayüzü (kotlin'den çağrıldığında daha az dağınık; lambda'nın eklenmiş arabirim adına ihtiyacı vardır, böylece bir nesneye ihtiyacınız yoktur; lambda işlev parantez kuralının dışında da kullanılamaz)

Kütüphanelerimizi Kotlin'e dönüştürürken, Java arabiriminde tüm arayüzleri Java kodunda bıraktık, çünkü Java'yı Kotlin'den Kotlin'den Kotlin'den çağırmak daha temizdi.


8

Arayüzünüze şu şekilde erişmeyi deneyin:

 object : MyInterface {
    override fun onSomething() { ... }
}

6

böyle bir Java sınıfınız varsa :

recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new RecyclerTouchListener.ClickListener()
        {
              //Your Code
        }));

Eğer Java dan bu kodu dönüştürmek sınırlandırmak KOTLIN böyle:

override fun showJozList (list : List<ResponseGetJuzList.Parameter4>) {
        adapter.addData(list)
        jozlist_recycler.addOnItemTouchListener(RecyclerTouchListener(
                activity ,
                jozlist_recycler ,
                object : RecyclerTouchListener.ClickListener
                    {
                          //Your Code
                    }))

Java Arayüzünü dönüştürmek :

new RecyclerTouchListener.ClickListener()

için Kotlin Arayüz Stili:

object : RecyclerTouchListener.ClickListener

1

Arabirim bir sınıfın dinleyici yöntemi içinse, arabirim tanımını işlev türüne değiştirin. Bu, kodu daha özlü hale getirir. Aşağıdakilere bakın.

Dinleyici tanımını içeren sınıf

// A class
private var mLocationMeasuredListener = (location: Location) -> Unit = {}

var setOnLocationMeasuredListener(listener: (location: Location) -> Unit) {
    mLocationMeasuredListener = listener
}

// somewhere in A class
mLocationMeasuredListener(location)

Başka bir sınıf

// B class
aClass.setOnLocationMeasuredListener { location ->
    // your code
}

-1
class YourClass : YourInterface {  
    override fun getTest() = "test"    
}

interface YourInterface {
    fun getTest(): String
}

val objectYourClass: YourInterface = YourClass()
print(objectYourClass.getTest())
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.