Ricerca…


Sintassi

  • fun Name ( Params ) = ...
  • nome divertente ( Params ) {...}
  • Fun Name ( Params ): Digitare {...}
  • divertente < Tipo argomento > Nome ( Params ): Tipo {...}
  • Inline divertimento Nome (Parametri): Type {...}
  • { ArgName : ArgType -> ...}
  • { ArgName -> ...}
  • { ArgNames -> ...}
  • {( ArgName : ArgType ): Type -> ...}

Parametri

Parametro Dettagli
Nome Nome della funzione
Parametri Valori assegnati alla funzione con un nome e tipo: Name : Type
genere Restituisce il tipo di funzione
Digita argomento Digitare il parametro utilizzato nella programmazione generica (non necessariamente il tipo restituito)
ArgName Nome del valore assegnato alla funzione
ArgType Specifier di tipo per ArgName
ArgNames Elenco di ArgName separato da virgole

Funzioni che assumono altre funzioni

Come visto in "Funzioni Lambda", le funzioni possono assumere altre funzioni come parametro. Il "tipo di funzione" che devi dichiarare funzioni che assumono altre funzioni è il seguente:

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

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

Ad esempio, potresti usare il tipo più vago, () -> Any? , per dichiarare una funzione che esegue due volte una funzione lambda:

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

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

Funzioni Lambda

Le funzioni Lambda sono funzioni anonime che vengono solitamente create durante una chiamata di funzione per fungere da parametro di funzione. Sono dichiarati dalle espressioni circostanti con {parentesi} - se sono necessari argomenti, questi vengono messi prima di una freccia -> .

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

L'ultima istruzione all'interno di una funzione lambda è automaticamente il valore di ritorno.

I tipi sono opzionali, se metti il ​​lambda su un posto dove il compilatore può inferire i tipi.

Argomenti multipli:

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

Se la funzione lambda necessita solo argomento, allora la lista argomento può essere omesso e il singolo argomento indicate con it invece.

{ "Your name is $it" }

Se l'unico argomento di una funzione è una funzione lambda, le parentesi possono essere completamente omesse dalla chiamata di funzione.

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

Riferimenti di funzione

Possiamo fare riferimento a una funzione senza effettivamente chiamarla anteponendo il nome della funzione a :: . Questo può quindi essere passato a una funzione che accetta qualche altra funzione come parametro.

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

Le funzioni senza ricevitore saranno convertite in (ParamTypeA, ParamTypeB, ...) -> ReturnType dove ParamTypeA , ParamTypeB ... sono il tipo di parametri della funzione e `ReturnType1 è il tipo di valore restituito dalla funzione.

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

Le funzioni con un ricevitore (che si tratti di una funzione di estensione o di una funzione membro) hanno una sintassi diversa. Devi aggiungere il nome del tipo del ricevitore prima dei due punti:

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.

Tuttavia, quando il ricevitore di una funzione è un oggetto, il ricevitore viene omesso dall'elenco dei parametri, poiché questi sono e sono solo un'istanza di tale 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.

Dal momento che kotlin 1.1, il riferimento alla funzione può anche essere limitato a una variabile, che viene quindi chiamata riferimento a una funzione limitata .

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

Nota questo esempio è dato solo per mostrare come funziona la funzione di riferimento limitata. È una cattiva pratica in tutti gli altri sensi.

C'è un caso speciale, però. Una funzione di estensione dichiarata come membro non può essere referenziata.

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

Funzioni base

Le funzioni sono dichiarate usando la fun parola chiave, seguita da un nome di funzione e da qualsiasi parametro. È anche possibile specificare il tipo di ritorno di una funzione, che per impostazione predefinita è Unit . Il corpo della funzione è racchiuso tra parentesi graffe {} . Se il tipo di ritorno è diverso Unit , il corpo deve emettere una dichiarazione di ritorno per ogni ramo di chiusura all'interno del corpo.

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

Una versione abbreviata dello stesso:

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

E il tipo può essere omesso poiché può essere dedotto:

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

Funzioni di stenografia

Se una funzione contiene solo un'espressione, possiamo omettere le parentesi graffe e usare invece un uguaglianza, come un'assegnazione di variabile. Il risultato dell'espressione viene restituito automaticamente.

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

Funzioni in linea

Le funzioni possono essere dichiarate in linea usando il prefisso inline e, in questo caso, si comportano come i macro in C, invece di essere chiamate, vengono sostituite dal codice del corpo della funzione in fase di compilazione. Ciò può portare a benefici prestazionali in alcune circostanze, principalmente laddove i lambda sono utilizzati come parametri di funzione.

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

Una differenza rispetto alle macro C è che le funzioni inline non possono accedere all'ambito da cui vengono chiamate:

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

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

Funzioni dell'operatore

Kotlin ci consente di fornire implementazioni per un insieme predefinito di operatori con una rappresentazione simbolica fissa (come + o * ) e una precedenza fissa. Per implementare un operatore, forniamo una funzione membro o una funzione di estensione con un nome fisso, per il tipo corrispondente. Funzioni che gli operatori di overload devono essere contrassegnati con il modificatore 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

Altre funzioni dell'operatore possono essere trovate qui



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow