Kotlin uzantısı işlevlerine Java'dan erişme


157

Java kodundan uzantı işlevlerine erişmek mümkün müdür?

Bir Kotlin dosyasında uzantı işlevini tanımladım.

package com.test.extensions

import com.test.model.MyModel

/**
 *
 */
public fun MyModel.bar(): Int {
    return this.name.length()
}

MyModel(Üretilen) bir java sınıfı nerede . Şimdi, normal java kodumda erişmek istedim:

MyModel model = new MyModel();
model.bar();

Ancak, bu işe yaramaz. IDE bar()yöntemi tanımaz ve derleme başarısız olur.

Kotlin'in statik fonksiyonuyla ne işe yarar?

public fun bar(): Int {
   return 2*2
}

kullanarak import com.test.extensions.ExtensionsPackageyani benim IDE doğru yapılandırılmış gibi görünüyor.

Kotlin belgelerinden tüm Java-birlikte çalışma dosyasını aradım ve çok fazla googledim, ancak bulamadım.

Neyi yanlış yapıyorum? Bu mümkün mü?


Lütfen detaylandırma çalışmıyor ? Derliyor mu, istisna atıyor mu, ya da ne? Ayrıca var mı import package com.test.extensions.MyModel?
meskobalazs

@meskobalazs düzenlenen cevabımı gör.
Lovis

@meskobalazs da, bunu bile ithal edemiyorum. Sadece ithal edebilirimcom.test.extensions.ExtensionsPackage
Lovis

Yanıtlar:


230

Bir dosyada bildirilen tüm Kotlin işlevleri varsayılan olarak aynı paket içindeki ve Kotlin kaynak dosyasından türetilen bir adla statik yöntemlere derlenecektir (İlk harf büyük ve ".kt" uzantısı "Kt" soneki ile değiştirilir ) . Genişletme işlevleri için oluşturulan yöntemlerde, genişletme işlevi alıcı tipinde ek bir ilk parametre bulunur.

Orijinal soruya uygulayan Java derleyicisi, Kotlin kaynak dosyasını example.kt adıyla görür.

package com.test.extensions

public fun MyModel.bar(): Int { /* actual code */ }

aşağıdaki Java sınıfı bildirilmiş gibi

package com.test.extensions

class ExampleKt {
    public static int bar(MyModel receiver) { /* actual code */ }
}

Genişletilmiş bakış açısıyla Java açısından hiçbir şey olmadıkça, bu tür yöntemlere erişmek için sadece nokta sözdizimini kullanamazsınız. Ancak yine de normal Java statik yöntemleri olarak çağrılabilir:

import com.test.extensions.ExampleKt;

MyModel model = new MyModel();
ExampleKt.bar(model);

Statik içe aktarma SampleKt sınıfı için kullanılabilir:

import static com.test.extensions.ExampleKt.*;

MyModel model = new MyModel();
bar(model);

1
Statik fonksiyonlar yazmadıkça Kotlin'den Java'ya uzantı kullanamayacağımı anladım.
AbdulMomen عبدالمؤمن

11
JFYI, Ayrıca sınıfın adını @file: JvmName ("<TheNameThatYouWant> Utils") ile de değiştirebilirsiniz.
crgarridos

3
parametrelerle bir uzantı oluşturursam ne olur?
AmirG

3
@AmirG parametreleri örneği izleyecektir. Bu durumda olurdubar(model, param1, param2);
Tim

Bu gerçekten hızlı bir yardımcı oldu, Çok teşekkürler
Vivek Gupta

31

Kotlin üst düzey uzantı işlevi Java statik yöntemleri olarak derlenmiştir.

Extensions.ktPakette verilen Kotlin dosyası foo.bar:

fun String.bar(): Int {
    ...
}

Eşdeğer Java kodu:

package foo.bar;

class ExtensionsKt {
    public static int bar(String receiver) { 
        ...
    }
}

Tabii Extensions.ktsatır içermediği sürece

@file:JvmName("DemoUtils")

Bu durumda Java statik sınıfı adlandırılır DemoUtils

Kotlin'de uzatma yöntemleri başka şekillerde de açıklanabilir. (Örneğin, bir üye işlevi olarak veya tamamlayıcı bir nesnenin uzantısı olarak.)


8

Aşağıdaki işleve sahip NumberFormatting.kt adlı bir Kotlin dosyası var

fun Double.formattedFuelAmountString(): String? {
    val format = NumberFormat.getNumberInstance()
    format.minimumFractionDigits = 2
    format.maximumFractionDigits = 2
    val string = format.format(this)
    return string
}

Java'da ben gerekli ithalat sonra aşağıdaki şekilde NumberFormattingKt dosya üzerinden basit erişimimport ....extensions.NumberFormattingKt;

String literString = NumberFormattingKt.formattedFuelAmountString(item.getAmount());

6

Önce Kotlin kodunuzdan oluşturulan gerçek Java kodunu Tools > Kotlin > Show Kotlin Bytecode, ardından öğesine tıklayarak görebilirsiniz Decompile. Bu size çok yardımcı olabilir. Sizin durumunuzda Java kodu aşağıdaki gibi görünecektirMyModelExtensions.kt

public final class MyModelExtensionsKt {
   public static final int bar(@NotNull MyModel $receiver) {
      Intrinsics.checkParameterIsNotNull($receiver, "$receiver");
      return $receiver.getName().length();
   }
}

aşağıdakileri @JvmNameiçeren dosyayı kullanarak bunu geliştirebilirsiniz bar:

@file:JvmName("MyModels")
package io.sspinc.datahub.transformation

public fun MyModel.bar(): Int {
    return this.name.length
}

ve bu kodla sonuçlanacaktır:

public final class MyModels {
   public static final int bar(@NotNull MyModel $receiver) {
      Intrinsics.checkParameterIsNotNull($receiver, "$receiver");
      return $receiver.getName().length();
   }
}

Kullanmak MyModels, Etkili Java'nın yardımcı program sınıfları için önerdiklerine uygundur. Ayrıca yönteminizi şu şekilde yeniden adlandırabilirsiniz:

public fun MyModel.extractBar(): Int {
    return this.name.length
}

Java tarafında deyimsel görünecektir:

MyModels.extractBar(model);

0

Sınıf dosyalarındaki işlevlerinizi çoğaltmanız gerekir:

Eski Utils.kt için Kotlin dosyası oluşturun

kodu giriniz

  class Utils {
                companion object {
                    @JvmStatic
                    fun String.getLength(): Int {//duplicate of func for java
                        return this.length
                    }
                }
            }

        fun String.getLength(): Int {//kotlin extension function
            return this.length
        }

VEYA

class Utils {
    companion object {

        @JvmStatic
        fun getLength(s: String): Int {//init func for java
            return s.length
        }
    }
}

fun String.getLength(): Int {//kotlin extension function
    return Utils.Companion.getLength(this)//calling java extension function in Companion
}

Kotlin kullanımında:

val str = ""
val lenth = str.getLength()

Java'da bunu kullanın:

String str = "";
 Integer lenth = Utils.getLength(str);

0

Benim için çalışıyor:

Kotlin KOTLIN

Java kodu resim açıklamasını buraya girin

Projem Java ile oluşturulan eski bir android projesidir; şimdi ilk kotlin dosyasını oluşturdum ve String uzantılarını fun ekledim String.isNotNullOrEmpty (): Boolean {...}

ve java dosyasından şunu kullanarak çağırabiliriz: StringUtilsKt.isNotNullOrEmpty (thestring).

Kotlin dosya adım StringUtils


-1

Buradaki diğer yanıtlar, Kotlin paket dosyasının en üst düzeyinde bulunan bir uzantı işlevini çağırma durumunu kapsar.

Ancak benim durumum, bir Sınıf içinde yer alan bir Extension işlevini çağırmak gerektiğiydi. Özellikle, bir Object ile uğraşıyordum.

Çözüm inanılmaz derecede basit .

Yapmanız gereken tek şey, eklenti işlevinize açıklama eklemek @JvmStaticve voila! Java kodunuz ona erişebilir ve kullanabilir.


Neden inişli çıkışlı? Cevabım doğru ve orijinal.
forresthopkinsa

-2

Böyle bir sınıfı genişlettiğinizde:

fun String.concatenatedLength(str: String): Int {
    return (this.length + str.length)
}

fun f() {
    var len = "one string".concatenatedLength("another string")
    println(len)
}

Bunu derleyecek:

import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

public final class ExampleKt {
  public static final int concatenatedLength(@NotNull String $receiver, @NotNull String str) {
    Intrinsics.checkParameterIsNotNull((Object) $receiver, (String) "$receiver");
    Intrinsics.checkParameterIsNotNull((Object) str, (String) "str");
    return $receiver.length() + str.length();
  }

  public static final void f() {
    int len = ExampleKt.concatenatedLength("one string", "another string");
    System.out.println(len);
  }
}

Burada daha fazla örnek var .


-3

Bildiğim kadarıyla bu mümkün değil. Uzantı dokümanlarını okuduğumdan,

public fun MyModel.bar(): Int {
    return this.name.length()
}

imzayla yeni bir yöntem oluşturur

public static int MyModelBar(MyModel obj) {
    return obj.name.length();
}

Daha sonra Kotlin, bu işlevi formun çağrılarıyla eşleştirir; myModel.bar()burada sınıfta bar()bulunmazsa, MyModelçıktığı imza ve adlandırma düzeniyle eşleşen statik yöntemler arar. Bunun, yalnızca statik olarak içe aktarılan ve tanımlanan yöntemleri geçersiz kılmayan uzantılarla ilgili açıklamalarından bir varsayım olduğunu unutmayın. Kaynaklarında kesin olarak bilecek kadar fazla şey bulamadım.

Bu nedenle, yukarıdakilerin doğru olduğu varsayılarak, eski bir java kodundan Kotlin uzantılarının çağrılması mümkün değildir, çünkü derleyici sadece bir nesnede bilinmeyen bir yöntem ve hata çıktığını görecektir.


3
Bu cevap doğru değil, erişilebilir. Kabul edilen cevaba bakınız.
Jayson Minard

Derleyici statik yöntemler aramıyor (özellikle Java statik yöntemleri değil). Aynı dosyada bildirilen veya içe aktarılan uzantı yöntemlerini arıyor.
Kirill Rakhman
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.