Kotlin: इंटरफ़ेस ... में निर्माता नहीं हैं


138

मैं अपने कुछ जावा कोड को कोटलिन में परिवर्तित कर रहा हूं और मुझे समझ में नहीं आ रहा है कि कोटलीन कोड में परिभाषित इंटरफेस को तुरंत कैसे किया जाए। एक उदाहरण के रूप में, मेरे पास एक इंटरफ़ेस है (जावा कोड में परिभाषित):

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

और फिर अपने कोटलिन कोड में मैं इस इंटरफेस को तुरंत समाप्त करता हूं:

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

और यह ठीक काम करता है। हालाँकि, जब मैं MyInterface को कोटलिन में परिवर्तित करता हूं:

interface MyInterface {
    fun onLocationMeasured(location: Location)
}

मुझे एक त्रुटि संदेश मिलता है: Interface MyListener does not have constructorsजब मैं इसे तुरंत करने की कोशिश करता हूं - हालांकि मुझे ऐसा लगता है कि सिंटैक्स के अलावा कुछ भी नहीं बदला है। क्या मुझे गलतफहमी है कि कोटलिन में इंटरफेस कैसे काम करते हैं?

जवाबों:


226

आपका जावा कोड एसएएम रूपांतरण पर निर्भर करता है - एक लैम्बडा का एक स्वचालित रूपांतरण एक एकल सार पद्धति के साथ इंटरफ़ेस में। एसएएम रूपांतरण वर्तमान में कोटलिन में परिभाषित इंटरफेस के लिए समर्थित नहीं है । इसके बजाय, आपको इंटरफ़ेस को लागू करने वाली एक अनाम वस्तु को परिभाषित करने की आवश्यकता है:

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

14
बहुत धन्यवाद। आपके द्वारा पोस्ट किए गए लिंक से, मैं समझता हूं कि Location -> Unitयदि संभव हो तो एकल-विधि इंटरफेस के बजाय कार्यात्मक प्रकार (जैसे ) का उपयोग करना बेहतर है - क्या यह सही है?
एलेफ एलेफ

4
यह सही है। आपको जहाँ भी संभव हो कार्यात्मक प्रकार का उपयोग करना चाहिए।
योव स्टर्नबर्ग

हालाँकि मेरे मामले में इंटरफ़ेस (सर्फेसटेक्स्टलरिस्टनर) के कई तरीके थे।
ताश पेमहिवा

बहुत बहुत धन्यवाद। इस उत्तर में अधिक पसंद या कुछ विशेष चिह्न होने चाहिए, couse यह बहुत ही उपयोगी जानकारी है और दुर्भाग्य से कुछ शिक्षार्थी बहुत ही भ्रमित हो सकते हैं जब वे लेख को कोटलिन या "कोटलिन इन एक्शन" द्वारा सीखते हैं जब वे एसएएम विषय को देखते हैं।
TT_W

"कोटलिन इन एक्शन" से, हां, आप शॉर्ट और क्लीनर कोड के लिए जावा के एसएएम परम में लैम्ब्डा का उपयोग कर सकते हैं, लेकिन कोटलिन का एसएएम नहीं, फंक्शन टाइप कोटलिन में प्रथम श्रेणी है, इसलिए, सैम को कोटलिन के लिए अर्थ नहीं है, टाइपेलियास के साथ फ़ंक्शन प्रकार अधिक कोटलिन शैली है।
vg0x00

17

सबसे अच्छा उपाय है कि आप अपने जावा इंटरफेस के टाइप-इन-प्लेस का उपयोग करें

typealias MyInterface = (Location) -> Unit

fun addLocationHandler(myInterface:MyInterface) {

}

इसे इस तरह पंजीकृत करें:

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

या यहां तक ​​कि क्लीनर

addLocationHandler { location -> ...}

इसे इस तरह लागू करें:

myInterface.invoke(location)

3 वर्तमान विकल्प प्रतीत होते हैं:

  • टाइपेलियास (जावा से गड़बड़ होने पर)
  • कोटलिन इंटरफ़ेस (गड़बड़ जब कोटलिन से कहा जाता है; आपको एक ऑब्जेक्ट बनाने की आवश्यकता है) यह एक बड़ा कदम है IMO।
  • जावा इंटरफ़ेस (कम गड़बड़ जब कोटलिन से पुकारा जाता है; लैंबडा को इंटरफ़ेस नाम की आवश्यकता होती है ताकि आपको किसी वस्तु की आवश्यकता न हो; फंक्शन कोष्ठक के बाहर लैंबडा का उपयोग नहीं किया जा सकता है)

अपने पुस्तकालयों को कोटलिन में परिवर्तित करते समय, हमने वास्तव में जावा कोड में सभी इंटरफेस छोड़ दिए, क्योंकि कोटलीन से कोटलिन की तुलना में कोटलिन से जावा को कॉल करने के लिए क्लीनर था।


8

इस तरह से अपने इंटरफ़ेस तक पहुंचने का प्रयास करें:

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

6

अगर आपके पास जावा क्लास इस तरह है:

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

आप इस कोड को जावा से कोटलिन में इस तरह बदलते हैं:

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

कन्वर्ट जावा इंटरफ़ेस :

new RecyclerTouchListener.ClickListener()

करने के लिए Kotlin इंटरफ़ेस शैली:

object : RecyclerTouchListener.ClickListener

1

यदि इंटरफ़ेस किसी वर्ग के श्रोता विधि के लिए है, तो इंटरफ़ेस परिभाषा को फ़ंक्शन प्रकार में बदलें। यह कोड को अधिक संक्षिप्त बनाता है। निम्नलिखित देखें।

श्रोता परिभाषा वाले वर्ग

// 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
}

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