Kotlin: Bir işlevi diğerine parametre olarak nasıl aktarabilirim?


142

Foo fonksiyonu verildiğinde:

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

Biz yapabiliriz:

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

Şimdi, aşağıdaki işleve sahip olduğumuzu varsayalım:

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

"Buz" u parametre olarak "foo" olarak geçirebilmemin bir yolu var mı? Gibi bir şey:

foo("a message", buz)

Yanıtlar:


201

::Bir işlev referansını belirtmek için kullanın ve ardından:

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

Kotlin 1.1'den beri , artık sınıf üyesi olan işlevleri (" Bağlı Çağrılabilir Referanslar "), işlev referans operatörünün önüne örnek ekleyerek kullanabilirsiniz:

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

foo("hi", thatOtherThing::buz)

foo("hi", this::buz)

1
yanlışsam lütfen beni düzeltin ama öyle görünüyor ki sadece üst düzey işlevler (yani bir sınıfa ait değil) bu şekilde geçilebilir; sınıf yöntemleri :-(
Jaja Harris

7
Bir üye referansı iletilebilir, ancak bu durumda bu, sınıfın bir örneğini gerektiren ilk parametrenin 2 parametreli bir işlevi olacaktır. Daha iyi bir yol, üye işlevini sınıfta kapalı olan bir lambda ile sarmalamaktır. Yukarıdakilerin hepsinin bir sınıfta olduğunu varsayarsak: fun something() { foo("hi", { buz(it) }) }
Jayson Minard

1
İle yapabilirsiniz KOTLIN 1.1 itibariyle, aynı sınıfta içinde faaliyet halinde geçirilebilir bir sınıfa aittir yapmak fonksiyonları görünüyorthis::function
Joe Maher

1
Ek olarak, işlev parametresini null yapılabilir yapmak isterseniz, tür bildirimini parantez içine ve sonunda bir soru işareti olacak şekilde sarın. örneğinbar: ((m: String) -> Unit)?
Aba

1
@MartyMiller onlar değil. Parametre mfoo içindir, diğer parametre değişken çubuğunda işleve aktarılan işlev türünün parametre adıdır.
Jayson Minard

12

Üye işlevi hakkında parametre olarak:

  1. Kotlin sınıfı statik üye işlevini desteklemez, bu nedenle üye işlevi şu şekilde çağrılamaz: Operator :: add (5, 4)
  2. Bu nedenle, üye işlevi Birinci sınıf işlevle aynı şekilde kullanılamaz.
  3. Kullanışlı bir yaklaşım, işlevi bir lambda ile sarmalamaktır. Zarif değil ama en azından işe yarıyor.

kod:

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
Geçerli KOTLIN, artık yapabilirsiniz referans olarak üye işlevini kullanın. Şimdi bu yanıtı güncellemelisiniz.
Jayson Minard

Kod çağıran yardımcı nesnede işlevleri tanımlayarak biraz daha iyi olun ve her seferinde yeni Operator örneği oluşturulmaz. Bu Java'da statik bir eğlence gibi görünecek
CAB

Harika bir çözüm, işlev bir sınıfta olduğunda işe yaradığını bulduğum tek yol bu. Çirkin ama güzel olduğunu düşünmüyorum, neredeyse açısal bir şablon değişkenine benziyor ama kod için.
gunslingor


4

Yöntem adından önce "::" kullanın

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

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

foo(::bar) Çıktı :Hello World


bu kod derlenmez. "function ()" bir parametre gerektiriyor
Giuseppe Giacoppo


1

Ayarlayıcı ve alıcı yöntemlerini geçmek istiyorsanız .

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

Kullanımı:

private var width: Int = 1

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

1

Jason Minard'ın cevabı iyi. Bu, bir lambda.

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

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

Hangi ile çağrılabilir foo("a message", buz).

Ayrıca, bunu bir typealias.

typealias qux = (m: String) -> Unit

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

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

0

Başka bir örnek:

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

-7

Birinci sınıf işlevler şu anda Kotlin'de desteklenmemektedir. Bunun eklenecek iyi bir özellik olup olmayacağı konusunda tartışmalar var. Şahsen yapmaları gerektiğini düşünüyorum.

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.