जावा से कोटलिन विस्तार कार्यों तक पहुँचना


157

क्या जावा कोड से विस्तार कार्यों को एक्सेस करना संभव है?

मैंने कोटलिन फ़ाइल में एक्सटेंशन फ़ंक्शन को परिभाषित किया।

package com.test.extensions

import com.test.model.MyModel

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

कहाँ MyModel(उत्पन्न) जावा वर्ग है। अब, मैं इसे अपने सामान्य जावा कोड में एक्सेस करना चाहता था:

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

हालाँकि, यह काम नहीं करता है। आईडीई bar()विधि को नहीं पहचानता है और संकलन विफल हो जाता है।

क्या काम करता है kotlin से एक स्थिर समारोह के साथ प्रयोग कर रहा है:

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

import com.test.extensions.ExtensionsPackageमेरे आईडीई के उपयोग से ऐसा लगता है कि यह ठीक से कॉन्फ़िगर किया गया है

मैंने कोटलिन डॉक्स से पूरे जावा-इंटरॉप फ़ाइल के माध्यम से खोज की और बहुत कुछ गुगला भी किया, लेकिन मुझे यह नहीं मिला।

मैं क्या गलत कर रहा हूं? क्या यह भी संभव है?


कृपया विस्तार से काम नहीं करता है ? क्या यह संकलन करता है, एक अपवाद फेंकता है, या क्या? आपके पास भी है import package com.test.extensions.MyModel?
मेसकोबलाज़्स

@meskobalazs मेरा संपादित उत्तर देखें।
लविस

@meskobalazs भी, मैं भी आयात नहीं कर सकते। मैं केवल आयात कर सकता हूँcom.test.extensions.ExtensionsPackage
Lovis

जवाबों:


230

एक फ़ाइल में घोषित सभी कोटलिन फ़ंक्शन एक ही पैकेज के भीतर एक वर्ग में स्थिर तरीकों से डिफ़ॉल्ट रूप से संकलित किए जाएंगे और कोटलिन स्रोत फ़ाइल से प्राप्त नाम के साथ (पहला अक्षर कैपिटल और कोटलिन ".kt" एक्सटेंशन "केटी" के साथ बदल दिया गया है। प्रत्यय के )। । एक्सटेंशन फ़ंक्शन के लिए उत्पन्न तरीकों में एक्सटेंशन फ़ंक्शन रिसीवर प्रकार के साथ एक अतिरिक्त पहला पैरामीटर होगा।

इसे मूल प्रश्न पर लागू करते हुए, जावा कंपाइलर नाम के साथ कोटलिन स्रोत फ़ाइल देखेंगे उदाहरण उदाहरण के

package com.test.extensions

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

मानो निम्न जावा वर्ग घोषित किया गया था

package com.test.extensions

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

जैसा कि जावा बिंदु से विस्तारित वर्ग के साथ कुछ भी नहीं होता है, आप ऐसे तरीकों का उपयोग करने के लिए केवल डॉट-सिंटैक्स का उपयोग नहीं कर सकते। लेकिन वे अभी भी सामान्य जावा स्थिर विधियों के रूप में सुगम हैं:

import com.test.extensions.ExampleKt;

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

उदाहरण के वर्ग के लिए स्थैतिक आयात का उपयोग किया जा सकता है:

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

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

1
मैं समझ गया, इसका मतलब है कि मैं कोटलिन से जावा तक एक्सटेंशन का उपयोग नहीं कर सकता जब तक कि मैं स्थिर कार्य नहीं लिखता?
अब्दुलमेन عبدالمؤمن

11
JFYI, आप @file: JvmName ("<TheNameThatYouWant> Utils") के साथ वर्ग का नाम भी बदल सकते हैं।
crgarridos

3
क्या होगा अगर मैं मापदंडों के साथ एक विस्तार बनाऊं?
अमीरगृह

3
@AmirG पैरामीटर उदाहरण का अनुसरण करेंगे। इस मामले में यह होगाbar(model, param1, param2);
टिम

यह वास्तव में एक त्वरित सहायता थी, बहुत बहुत धन्यवाद
विवेक गुप्ता

31

कोटलिन शीर्ष-स्तरीय विस्तार फ़ंक्शन को जावा स्टैटिक विधियों के रूप में संकलित किया गया है।

Extensions.ktपैकेज में कोटलिन फ़ाइल को देखते हुए foo.bar:

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

बराबर जावा कोड होगा:

package foo.bar;

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

जब तक, कि Extensions.ktलाइन निहित है

@file:JvmName("DemoUtils")

किस स्थिति में जावा स्टैटिक क्लास का नाम दिया जाएगा DemoUtils

कोटलिन में, विस्तार के तरीकों को अन्य तरीकों से घोषित किया जा सकता है। (उदाहरण के लिए, सदस्य फ़ंक्शन के रूप में या साथी ऑब्जेक्ट के विस्तार के रूप में।)


8

मेरे पास एक Kotlin फ़ाइल है जिसका नाम NumberFormatting.kt है जिसमें निम्नलिखित फ़ंक्शन हैं

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

जावा में मैं आवश्यक आयात के बाद निम्न तरीके से फ़ाइल नंबरफॉर्म पर इसे एक्सेस करता हूंimport ....extensions.NumberFormattingKt;

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

6

आप हमेशा वास्तविक जावा कोड देख सकते हैं, जो आपके कोटलिन कोड से उत्पन्न हो रहा है Tools > Kotlin > Show Kotlin Bytecode, फिर क्लिक करके Decompile। यह आपकी जबरदस्त मदद कर सकता है। आपके मामले में यदि आपके पास जावा कोड इस तरह दिखाई देगाMyModelExtensions.kt

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

आप @JvmNameफ़ाइल युक्त पर उपयोग करके इस पर सुधार कर सकते हैं bar:

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

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

और इस कोड में परिणाम होगा:

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

का उपयोग करते हुए MyModelsक्या प्रभावी जावा उपयोगिता कक्षाओं के लिए पता चलता है के साथ लाइन में है। आप इस तरह से अपनी विधि का नाम बदल सकते हैं:

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

तब जावा की ओर से यह मुहावरेदार लगेगा:

MyModels.extractBar(model);

0

आपको क्लास फ़ाइल्स में अपने कार्यों की डुप्लिकेट करने की आवश्यकता है:

पूर्व Utils.kt के लिए, कोटलिन फ़ाइल बनाएँ

कोड दर्ज करें

  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
        }

या

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
}

कोटलिन उपयोग में:

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

जावा में इसका उपयोग करें:

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

0

इससे मेरा काम बनता है:

Kotlin kotlin

जावा कोड यहाँ छवि विवरण दर्ज करें

मेरा प्रोजेक्ट जावा के साथ बनाया गया एक पुराना एंड्रॉइड प्रोजेक्ट है; अब मैंने पहली कोटलिन फ़ाइल बनाई और स्ट्रिंग एक्सटेंशन मज़ा जोड़ा String.isNotNullOrEmpty (): बूलियन {...}

और मैं इसे जावा फ़ाइल से कॉल कर सकता हूं: StringUtilsKt.isNotNullOrEmpty (thestring)।

मेरी कोटलिन फ़ाइल का नाम StringUtils है


-1

अन्य उत्तर यहां कोटलिन पैकेज फ़ाइल के शीर्ष स्तर पर स्थित एक्सटेंशन फ़ंक्शन को कॉल करने के मामले को कवर करते हैं।

हालांकि, मेरा मामला यह था कि मुझे क्लास के अंदर स्थित एक्सटेंशन फ़ंक्शन को कॉल करने की आवश्यकता थी। विशेष रूप से, मैं एक वस्तु के साथ काम कर रहा था।

समाधान अविश्वसनीय रूप से सरल है

आपको बस इतना करना है कि आप अपने एक्सटेंशन फंक्शन को एनोटेट करें @JvmStatic, और वॉइला! आपका जावा कोड इसे एक्सेस करने और इसका उपयोग करने में सक्षम होगा।


क्यों होता है पतन? मेरा उत्तर सही और मूल है।
forresthopkinsa

-2

जब आप इस तरह एक वर्ग का विस्तार करते हैं:

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

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

यह इस पर संकलित करेगा:

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);
  }
}

यहां और भी उदाहरण हैं


-3

जहाँ तक मैं बता सकता हूँ यह संभव नहीं है। एक्सटेंशन डॉक्स के मेरे पढ़ने से, ऐसा प्रतीत होता है

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

हस्ताक्षर के साथ एक नई विधि बनाता है

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

फिर, कोटलिन उस फॉर्म के कॉल पर काम करता है myModel.bar(), जहां यदि bar()वह MyModelक्लास में नहीं पाया जाता है तो यह हस्ताक्षर और नामकरण योजना के स्थिर तरीकों की तलाश करता है।ध्यान दें कि यह केवल स्टेटमेंट्स के इम्पोर्टेन्ट होने के बारे में उनके स्टेटमेंट से एक धारणा है और परिभाषित तरीकों को ओवरराइड नहीं कर रहा है। मुझे यकीन है कि पता करने के लिए उनके स्रोत में बहुत दूर नहीं गया है।

इसलिए, यह मान लेना कि सत्य है कि कोटलिन एक्सटेंशन के लिए सादे पुराने जावा कोड से कॉल करने का कोई तरीका नहीं है, क्योंकि कंपाइलर को एक अज्ञात विधि दिखाई देगी जो किसी ऑब्जेक्ट और एरर आउट पर कॉल की जाएगी।


3
यह उत्तर सही नहीं है, उन्हें एक्सेस किया जा सकता है। स्वीकृत उत्तर देखें।
जैसन मिनार्ड

और संकलक स्थिर विधियों (विशेषकर जावा स्थिर विधियों) की तलाश नहीं कर रहा है। यह एक्सटेंशन विधियों की तलाश कर रहा है जो एक ही फ़ाइल में घोषित या आयात किए गए हैं।
किरिल रहमान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.