Kotlin: एक फ़ंक्शन को दूसरे के पैरामीटर के रूप में कैसे पारित किया जाए?


141

दिए गए फ़ंक्शन फू:

fun foo(m: String, bar: (m: String) -> Unit) {
    bar(m)
}

हम कर सकते हैं:

foo("a message", { println("this is a message: $it") } )
//or 
foo("a message")  { println("this is a message: $it") }

अब, हम कहते हैं कि हमारे पास निम्नलिखित कार्य हैं:

fun buz(m: String) {
   println("another message: $m")
}

क्या कोई तरीका है जो मैं "फू" के पैरामीटर के रूप में "बज़" पास कर सकता हूं? कुछ इस तरह:

foo("a message", buz)

जवाबों:


199

::फ़ंक्शन संदर्भ को इंगित करने के लिए उपयोग करें , और फिर:

fun foo(m: String, bar: (m: String) -> Unit) {
    bar(m)
}

// my function to pass into the other
fun buz(m: String) {
    println("another message: $m")
}

// someone passing buz into foo
fun something() {
    foo("hi", ::buz)
}

कोटलिन 1.1 के बाद से अब आप फ़ंक्शन के साथ फ़ंक्शन का उपयोग कर सकते हैं (" कॉल योग्य संदर्भों को बाध्य करें "), उदाहरण के साथ फ़ंक्शन संदर्भ ऑपरेटर को प्रीफ़िक्स करके:

foo("hi", OtherClass()::buz)

foo("hi", thatOtherThing::buz)

foo("hi", this::buz)

1
कृपया मुझे सही करें अगर मैं गलत हूं, लेकिन ऐसा लगता है कि केवल शीर्ष स्तर के कार्य (अर्थात एक वर्ग से संबंधित नहीं हैं) को इस तरीके से पारित किया जा सकता है; कक्षा के तरीके नहीं कर सकते हैं :-(
जाजा हैरिस

7
एक सदस्य संदर्भ को पास किया जा सकता है, लेकिन इस मामले में 2 पैरामीटर फ़ंक्शन होगा जिसमें पहले पैरामीटर के लिए कक्षा की एक आवृत्ति की आवश्यकता होगी। एक बेहतर तरीका यह है कि सदस्य फ़ंक्शन को लैम्बडा के साथ लपेटें जो कि कक्षा पर बंद हो। उपरोक्त सभी को एक वर्ग में मान लिया गया था: fun something() { foo("hi", { buz(it) }) }
जैसन मिनार्ड

1
ऐसा लगता है कि फ़ंक्शंस जो एक वर्ग से संबंधित हैं उन्हें पास किया जा सकता है यदि आप एक ही कक्षा के भीतर काम कर रहे हैं, तो कोटलिन 1.1 के साथ आप इसे कर सकते हैंthis::function
जो मैहर

1
इसके अलावा, यदि आप फ़ंक्शन पैरामीटर को अशक्त बनाना चाहते हैं, तो अंत में एक प्रश्न चिह्न के साथ कोष्ठक में घोषित प्रकार को लपेटें। जैसेbar: ((m: String) -> Unit)?
अभा

1
@MartyMiller वे नहीं हैं। पैरामीटर mfoo के लिए है, अन्य पैरामीटर फ़ंक्शन प्रकार का पैरामीटर नाम है जो फ़ंक्शन को चर बार में पारित किया गया है।
जैसन मिनार्ड

12

पैरामीटर के रूप में सदस्य फ़ंक्शन के बारे में:

  1. कोटलिन वर्ग स्थिर सदस्य फ़ंक्शन का समर्थन नहीं करता है, इसलिए सदस्य फ़ंक्शन को लागू नहीं किया जा सकता है जैसे: ऑपरेटर :: ऐड (5, 4)
  2. इसलिए, सदस्य फ़ंक्शन को प्रथम श्रेणी फ़ंक्शन के समान उपयोग नहीं किया जा सकता है।
  3. एक उपयोगी दृष्टिकोण एक लंबो के साथ फ़ंक्शन को लपेटना है। यह सुरुचिपूर्ण नहीं है, लेकिन कम से कम यह काम कर रहा है।

कोड:

class Operator {
    fun add(a: Int, b: Int) = a + b
    fun inc(a: Int) = a + 1
}

fun calc(a: Int, b: Int, opr: (Int, Int) -> Int) = opr(a, b)
fun calc(a: Int, opr: (Int) -> Int) = opr(a)

fun main(args: Array<String>) {
    calc(1, 2, { a, b -> Operator().add(a, b) })
    calc(1, { Operator().inc(it) })
}

4
वर्तमान कोटलिन में, अब आप एक संदर्भ के रूप में एक सदस्य फ़ंक्शन का उपयोग कर सकते हैं। आपको अब इस उत्तर को अपडेट करना चाहिए।
जैसन मिनार्ड

साथी ऑब्जेक्ट में फ़ंक्शन को परिभाषित करने से कॉलिंग कोड थोड़ा बेहतर हो जाता है और ऑपरेटर का कोई नया उदाहरण हर बार नहीं मिलता है। यह जावा में एक स्थैतिक मज़ा की तरह दिखेगा
सीएबी

महान समाधान, यह एकमात्र तरीका है जो मैंने पाया कि जब एक कक्षा में कार्य होता है। मैं इसे बदसूरत लेकिन सुंदर नहीं मानता, लगभग कोणीय टेम्पलेट चर जैसा दिखता है, लेकिन कोड के लिए।
गनलिंग्लर


4

बस विधि नाम से पहले "::" का उपयोग करें

fun foo(function: () -> (Unit)) {
   function()
}

fun bar() {
    println("Hello World")
}

foo(::bar) आउटपुट :Hello World


यह कोड संकलित नहीं करता है। "फ़ंक्शन ()" के लिए एक पैरामीटर की आवश्यकता होती है
Giuseppe Giacoppo


1

अगर आप सेटर और गेट्टर मेथड पास करना चाहते हैं ।

private fun setData(setValue: (Int) -> Unit, getValue: () -> (Int)) {
    val oldValue = getValue()
    val newValue = oldValue * 2
    setValue(newValue)
}

उपयोग:

private var width: Int = 1

setData({ width = it }, { width })

1

जेसन मिनार्ड का जवाब एक अच्छा है। यह भी एक का उपयोग कर प्राप्त किया जा सकता है lambda

fun foo(m: String, bar: (m: String) -> Unit) {
    bar(m)
}

val buz = { m: String ->
    println("another message: $m")
}

जिसे साथ बुलाया जा सकता है foo("a message", buz)

तुम भी एक का उपयोग करके यह थोड़ा और DRY बना सकते हैं typealias

typealias qux = (m: String) -> Unit

fun foo(m: String, bar: qux) {
    bar(m)
}

val buz: qux = { m ->
    println("another message: $m")
}

0

एक और उदाहरण:

 fun foo(x:Int, Multiply: (Int) -> (Int)) {
    println(Multiply(x))
 }
 fun bar(x:Int):Int{
    return  x * x
 }
 foo(10, ::bar)

-7

प्रथम श्रेणी के कार्य वर्तमान में कोटलिन में समर्थित नहीं हैं। इस बारे में बहस चल रही है कि क्या यह जोड़ने के लिए एक अच्छी सुविधा होगी। मुझे व्यक्तिगत रूप से लगता है कि उन्हें चाहिए।

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