Buscar..


Sintaxis

  • Nombre divertido ( Params ) = ...
  • Nombre divertido ( Params ) {...}
  • Nombre divertido ( Params ): Tipo {...}
  • fun < Type Argument > Name ( Params ): Type {...}
  • Nombre de diversión en línea ( Parámetros ): Escriba {...}
  • { ArgName : ArgType -> ...}
  • { ArgName -> ...}
  • { ArgNames -> ...}
  • {( ArgName : ArgType ): Type -> ...}

Parámetros

Parámetro Detalles
Nombre Nombre de la función
Parámetros Valores dados a la función con un nombre y tipo: Name : Type
Tipo Tipo de retorno de la función.
Tipo de argumento Tipo de parámetro utilizado en la programación genérica (no necesariamente tipo de retorno)
ArgName Nombre del valor dado a la función.
ArgType Especificador de tipo para ArgName
ArgNames Lista de ArgName separados por comas

Funciones que toman otras funciones

Como se ve en "Funciones Lambda", las funciones pueden tomar otras funciones como un parámetro. El "tipo de función" que deberá declarar funciones que aceptan otras funciones es el siguiente:

# Takes no parameters and returns anything
() -> Any?

# Takes a string and an integer and returns ReturnType
(arg1: String, arg2: Int) -> ReturnType

Por ejemplo, podría usar el tipo más vago, () -> Any? , para declarar una función que ejecuta una función lambda dos veces:

fun twice(x: () -> Any?) {
    x(); x();
}

fun main() {
    twice {
        println("Foo")
    } # => Foo
      # => Foo
}

Funciones Lambda

Las funciones Lambda son funciones anónimas que generalmente se crean durante una llamada de función para actuar como un parámetro de función. Se declaran mediante expresiones circundantes con {llaves}: si se necesitan argumentos, estos se colocan antes de una flecha -> .

{ name: String ->
    "Your name is $name" //This is returned
}

La última declaración dentro de una función lambda es automáticamente el valor de retorno.

Los tipos son opcionales, si coloca la lambda en un lugar donde el compilador puede inferir los tipos.

Múltiples argumentos:

{ argumentOne:String, argumentTwo:String ->
    "$argumentOne - $argumentTwo"
}

Si la función lambda sólo necesita un argumento, a continuación, la lista de argumentos puede ser omitido y el argumento solo se refiere al uso it en su lugar.

{ "Your name is $it" }

Si el único argumento de una función es una función lambda, los paréntesis se pueden omitir completamente de la llamada a la función.

# These are identical
listOf(1, 2, 3, 4).map { it + 2 }
listOf(1, 2, 3, 4).map({ it + 2 })

Referencias de funciones

Podemos hacer referencia a una función sin realmente llamarla prefijando el nombre de la función con :: . Esto se puede pasar a una función que acepta alguna otra función como parámetro.

fun addTwo(x: Int) = x + 2
listOf(1, 2, 3, 4).map(::addTwo) # => [3, 4, 5, 6]

Las funciones sin receptor se convertirán a (ParamTypeA, ParamTypeB, ...) -> ReturnType donde ParamTypeA , ParamTypeB ... son el tipo de parámetros de la función y `ReturnType1 es el tipo de valor de retorno de la función.

fun foo(p0: Foo0, p1: Foo1, p2: Foo2): Bar {
    //...
}
println(::foo::class.java.genericInterfaces[0]) 
// kotlin.jvm.functions.Function3<Foo0, Foo1, Foo2, Bar>
// Human readable type: (Foo0, Foo1, Foo2) -> Bar

Las funciones con un receptor (ya sea una función de extensión o una función miembro) tienen una sintaxis diferente. Debe agregar el nombre de tipo del receptor antes de los dos puntos dobles:

class Foo
fun Foo.foo(p0: Foo0, p1: Foo1, p2: Foo2): Bar {
    //...
}
val ref = Foo::foo
println(ref::class.java.genericInterfaces[0]) 
// kotlin.jvm.functions.Function4<Foo, Foo0, Foo1, Foo2, Bar>
// Human readable type: (Foo, Foo0, Foo1, Foo2) -> Bar
// takes 4 parameters, with receiver as first and actual parameters following, in their order

// this function can't be called like an extension function, though
val ref = Foo::foo
Foo().ref(Foo0(), Foo1(), Foo2()) // compile error

class Bar {
    fun bar()
}
print(Bar::bar) // works on member functions, too.

Sin embargo, cuando el receptor de una función es un objeto, el receptor se omite de la lista de parámetros, porque este es y solo es una instancia de ese tipo.

object Foo
fun Foo.foo(p0: Foo0, p1: Foo1, p2: Foo2): Bar {
    //...
}
val ref = Foo::foo
println(ref::class.java.genericInterfaces[0]) 
// kotlin.jvm.functions.Function3<Foo0, Foo1, Foo2, Bar>
// Human readable type: (Foo0, Foo1, Foo2) -> Bar
// takes 3 parameters, receiver not needed

object Bar {
    fun bar()
}
print(Bar::bar) // works on member functions, too.

Desde kotlin 1.1, la referencia de función también puede estar limitada a una variable, que luego se denomina referencia de función limitada .

1.1.0
fun makeList(last: String?): List<String> {
    val list = mutableListOf("a", "b", "c")
    last?.let(list::add)
    return list
}

Tenga en cuenta que este ejemplo se proporciona solo para mostrar cómo funciona la referencia de función acotada. Es una mala práctica en todos los demás sentidos.

Sin embargo, hay un caso especial. Una función de extensión declarada como miembro no puede ser referenciada.

class Foo
class Bar {
    fun Foo.foo() {}
    val ref = Foo::foo // compile error
}

Funciones básicas

Las funciones se declaran utilizando la palabra clave fun , seguida de un nombre de función y cualquier parámetro. También puede especificar el tipo de retorno de una función, que por defecto es Unit . El cuerpo de la función está encerrado entre llaves {} . Si el tipo de devolución es distinto de Unit , el cuerpo debe emitir una declaración de devolución para cada rama de terminación dentro del cuerpo.

fun sayMyName(name: String): String {
    return "Your name is $name" 
} 

Una versión abreviada de la misma:

fun sayMyName(name: String): String = "Your name is $name" 

Y el tipo se puede omitir ya que se puede inferir:

fun sayMyName(name: String) = "Your name is $name" 

Funciones abreviadas

Si una función contiene solo una expresión, podemos omitir los corchetes y usar un igual en su lugar, como una asignación de variable. El resultado de la expresión se devuelve automáticamente.

fun sayMyName(name: String): String = "Your name is $name" 

Funciones en línea

Las funciones se pueden declarar en línea usando el prefijo en inline , y en este caso actúan como macros en C, en lugar de ser llamadas, se reemplazan por el código del cuerpo de la función en el momento de la compilación. Esto puede llevar a beneficios de rendimiento en algunas circunstancias, principalmente cuando las lambdas se utilizan como parámetros de función.

inline fun sayMyName(name: String) = "Your name is $name" 

Una diferencia de las macros de C es que las funciones en línea no pueden acceder al ámbito desde el que se llaman:

inline fun sayMyName() = "Your name is $name"

fun main() {
    val name = "Foo"
    sayMyName() # => Unresolved reference: name
}

Funciones del operador

Kotlin nos permite proporcionar implementaciones para un conjunto predefinido de operadores con representación simbólica fija (como + o * ) y precedencia fija. Para implementar un operador, proporcionamos una función miembro o una función de extensión con un nombre fijo, para el tipo correspondiente. Las funciones que sobrecargan a los operadores deben estar marcadas con el modificador de operator :

data class IntListWrapper (val wrapped: List<Int>) {
    operator fun get(position: Int): Int = wrapped[position]
}

val a = IntListWrapper(listOf(1, 2, 3))
a[1] // == 2

Más funciones del operador se pueden encontrar aquí



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow