Kotlin : 함수를 다른 매개 변수로 전달하는 방법은 무엇입니까?


141

주어진 함수 foo :

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

"buz"를 "foo"에 매개 변수로 전달할 수있는 방법이 있습니까? 다음과 같은 것 :

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

Kotlin 1.1부터는 함수 참조 연산자에 인스턴스 접두어를 붙여 클래스 멤버 인 함수 ( " Bound Callable References ")를 사용할 수 있습니다 .

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

foo("hi", thatOtherThing::buz)

foo("hi", this::buz)

1
내가 틀렸다면 나를 수정하십시오. 그러나 최상위 함수 (예 : 클래스에 속하지 않음)만이 이런 식으로 전달 될 수 있습니다. 클래스 메소드는 수 없습니다 :-(
Jaja Harris

7
멤버 참조는 전달 될 수 있지만이 경우 클래스의 인스턴스를 요구하는 첫 번째 매개 변수가있는 2 개의 매개 변수 함수입니다. 더 좋은 방법은 멤버 함수를 클래스에서 닫은 람다로 감싸는 것입니다. 위의 모든 내용이 클래스에 있다고 가정 : fun something() { foo("hi", { buz(it) }) }
Jayson Minard

1
kotlin 1.1에서와 같이 같은 클래스 내에서 작업하는 경우 클래스에 속하는 함수를 전달할 수 있습니다.this::function
Joe Maher

1
또한 함수 매개 변수를 nullable로 만들려면 끝에 선언을 물음표로 괄호 안에 형식 선언을 래핑하십시오. 예 :bar: ((m: String) -> Unit)?
Aba

1
@MartyMiller 그들은 아닙니다. 매개 변수 m는 foo 용이고 다른 매개 변수는 변수 막대에 함수에 전달 된 함수 유형의 매개 변수 이름입니다.
Jayson Minard

12

매개 변수로서 멤버 함수 정보 :

  1. Kotlin 클래스는 정적 멤버 함수를 지원하지 않으므로 다음과 같이 멤버 함수를 호출 할 수 없습니다. Operator :: add (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
현재 Kotlin에서는 이제 멤버 함수를 참조로 사용할 있습니다. 이제이 답변을 업데이트해야합니다.
Jayson Minard

컴패니언 객체 호출 코드에서 함수를 정의하면 조금 나아지고 매번 Operator 인스턴스가 새로 생성되지 않습니다. 이것은 자바에서 정적 인 재미처럼 보일 것입니다
CAB

훌륭한 해결책은 이것이 함수가 클래스에있을 때 작동하는 유일한 방법입니다. 나는 그것이 추악하지만 아름답다고 생각하지 않으며, 거의 각진 템플릿 변수처럼 보이지만 코드입니다.
gunslingor


4

메소드 이름 앞에 "::"를 사용하십시오.

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

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

foo(::bar) 출력 :Hello World


이 코드는 컴파일되지 않습니다. "function ()"에는 매개 변수가 필요합니다
Giuseppe Giacoppo


1

settergetter 메소드 를 전달하려는 경우 .

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

Jason Minard의 대답은 좋은 것입니다. 이것은를 사용하여 달성 할 수도 있습니다 lambda.

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

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

로 호출 할 수 있습니다 foo("a message", buz).

를 사용하여 이것을 조금 더 건조하게 만들 수도 있습니다 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

일류 함수는 현재 Kotlin에서 지원되지 않습니다. 이것이 추가하기에 좋은 기능인지에 대한 논쟁이있었습니다. 나는 개인적으로 그들이해야한다고 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.