Extension function in Kotlin: cos'è, sintassi e applicazione

Autore: IT Sectr Pubblicato: 2026-06-21 Tempo di lettura: 9 min

extension function — un meccanismo di Kotlin che consente di aggiungere nuovi metodi a classi esistenti senza ereditarietà e senza modificare il codice sorgente. La funzione viene dichiarata con un prefisso sotto forma di tipo ricevente e viene chiamata come un metodo normale di quel tipo. Secondo Kotlin Documentation, 2025, le extension functions vengono compilate in metodi statici con il ricevente come primo parametro, garantendo zero overhead in fase di esecuzione rispetto alle chiamate normali.

Punti chiave

  • Extension function — un metodo con un tipo ricevente, chiamato come membro della classe senza ereditarietà
  • Tipo ricevente specificato tramite un punto prima del nome della funzione: fun Type.method()
  • Dispatch statico — l'extension function non è virtuale, viene chiamata in base al tipo della variabile
  • Import obbligatorio: le extension functions non sono membri della classe e richiedono l'import
  • I membri della classe hanno priorità: se il metodo corrisponde, viene chiamato il membro della classe, non l'estensione

Cos'è una extension function in Kotlin?

Una extension function è una funzione dichiarata all'esterno di una classe ma chiamata come suo metodo. Prende un tipo ricevente a cui viene aggiunto il nuovo metodo. All'interno della funzione, la parola chiave this si riferisce all'istanza del tipo ricevente. Questo approccio consente di estendere classi finali, classi di librerie di terze parti e persino tipi primitivi senza creare wrapper.

A differenza di Java, dove aggiungere un metodo a una classe esistente richiede l'ereditarietà o una classe di utilità statica, Kotlin offre una soluzione elegante senza boilerplate. Secondo uno studio della Kotlin Foundation (2024), le extension functions sono tra le cinque funzionalità più utilizzate del linguaggio — il 78% degli sviluppatori Kotlin le usa nel lavoro quotidiano.

Il compilatore Kotlin traduce una extension function in un metodo statico in cui l'istanza del ricevente viene passata come primo argomento. Ciò significa che le extension functions non modificano il bytecode della classe di destinazione e non violano l'incapsulamento — solo i campi e i metodi pubblici del ricevente sono accessibili.

Utilizza le extension functions per scrivere funzioni di utilità pulite che sono logicamente legate a un tipo specifico ma non possono essere aggiunte al suo codice sorgente.

Sintassi di extension function: dichiarazione e chiamata

La sintassi di base di una extension function: il nome del tipo ricevente, un punto, il nome della funzione, poi i parametri e il tipo di ritorno. All'interno della funzione, il ricevente è accessibile tramite this.

kotlin
// Extension function for String
fun String.isEmail(): Boolean {
    return this.contains("@") && this.contains(".")
}

// Called as regular String method
val result = "user@example.com".isEmail() // true

In questo esempio, isEmail() diventa disponibile per tutte le stringhe. All'interno della funzione, this si riferisce alla stringa stessa su cui viene chiamato il metodo. Kotlin consente di omettere this nella maggior parte dei casi — si può scrivere semplicemente contains("@") invece di this.contains("@").

Extension function con parametri

Le extension functions possono accettare parametri aggiuntivi e restituire valori di qualsiasi tipo. Questo le rende funzioni a tutti gli effetti, non solo zucchero sintattico.

kotlin
fun List<Int>.defaultIfEmpty(default: Int): List<Int> {
    if (this.isEmpty()) return listOf(default)
    return this
}

val populated = listOf(1, 2).defaultIfEmpty(0)
val empty = listOf<Int>().defaultIfEmpty(0)

Il parametro default definisce il valore restituito per una lista vuota. Una extension function può essere generica — il tipo List è generico, sebbene l'esempio utilizzi un List specifico.

Dispatch statico e ricevente

Le extension functions in Kotlin utilizzano il dispatch statico, non il dispatch virtuale. Questa è una differenza fondamentale rispetto ai metodi di classe normali. Quale extension function verrà chiamata è determinato in fase di compilazione dal tipo statico della variabile, non dal suo tipo effettivo in fase di esecuzione.

kotlin
open class Animal
class Dog : Animal()

fun Animal.speak() = "Animal sound"
fun Dog.speak() = "Woof"

fun test() {
    val animal: Animal = Dog()
    println(animal.speak()) // "Animal sound" — static type Animal

    val dog: Dog = Dog()
    println(dog.speak()) // "Woof" — static type Dog
}

Anche se la variabile animal punta a un'istanza di Dog, viene chiamata l'extension function per Animal perché il tipo statico della variabile è Animal. Se speak() fosse un metodo virtuale di classe, verrebbe chiamato Dog.speak(). Questo comportamento è importante da considerare quando si progettano API con extension functions.

Import e ambito delle extension functions

Le extension functions non sono membri della classe — sono funzioni normali che richiedono un import per essere utilizzate in un altro file. Kotlin fornisce due opzioni di import: per nome della funzione o con rinominazione.

kotlin
// Import by name
import com.example.extensions.isEmail

// Import with alias (to resolve conflicts)
import com.example.extensions.isEmail as isValidEmail

// Call after import
val valid = "test@test.com".isEmail()

La rinominazione tramite as è utile per conflitti di nomi — ad esempio, se due librerie forniscono una extension function con lo stesso nome per lo stesso tipo. In questo caso, è possibile importarne una con un nome diverso e chiamarla usando il nuovo nome.

Ambito

Le extension functions possono essere dichiarate a diversi livelli:

LivelloVisibilitàEsempio
Top-levelIntero progetto dopo l'importfun String.isEmail()
Member extensionAll'interno della classe proprietariaclass A { fun B.ext() }
LocalAll'interno di una funzionefun test() { fun String.ext() }

Le member extension functions sono un caso speciale in cui una extension function viene dichiarata all'interno di un'altra classe. In questo caso, sia il ricevente (this della funzione) che i membri della classe esterna sono accessibili all'interno dell'extension function.

Priorità dei membri della classe sulle estensioni

Se una classe ha un metodo con la stessa firma di una extension function, viene sempre chiamato il membro della classe. Una extension function non sovrascrive mai un metodo di classe — questa è una decisione architetturale per prevenire sovrascritture accidentali.

kotlin
class User {
    fun greet() = "Hello from class"
}

fun User.greet() = "Hello from extension"

fun main() {
    val user = User()
    println(user.greet()) // "Hello from class"
}

Anche se l'extension function viene definita successivamente e ha la stessa firma, il compilatore sceglierà il metodo della classe. Il compilatore Kotlin emette un avviso quando rileva questa situazione. L'unico modo per chiamare l'extension function quando esiste un metodo di classe è invocarla come funzione normale: greet(user).

Esempi pratici di extension functions

Nello sviluppo Android, le extension functions sono diventate uno strumento standard per lavorare con View, Context e fragment. La libreria Android KTX è costruita sulle extension functions, fornendo wrapper convenienti sull'API Android.

kotlin
// Extension function for working with View
fun View.show() {
    visibility = View.VISIBLE
}

fun View.hide() {
    visibility = View.GONE
}

// Extension function for Context — toast
fun Context.toast(message: String) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

// Extension function as DSL builder
fun String.colorFormat(color: String): String =
    "$color$this\u001b[0m"

L'extension function toast() rende concisi i chiamate dipendenti da Context: invece di scrivere Toast.makeText(context, message, length).show(), basta scrivere context.toast("Testo"). Questo riduce il boilerplate e rende il codice più leggibile.

Domande frequenti

Si può sovrascrivere una extension function in una sottoclasse?

No, le extension functions utilizzano il dispatch statico. Se dichiari una extension function per una classe base e la stessa per una sottoclasse, quale verrà chiamata è determinata dal tipo statico della variabile in fase di compilazione, non dal tipo effettivo in fase di esecuzione.

Come funzionano le extension functions con i tipi nullable?

Puoi dichiarare extension functions per tipi riceventi nullable: fun String?.isNullOrEmail(). All'interno di tale funzione, this può essere null, quindi devi utilizzare operatori di chiamata sicura o controlli espliciti di null.

Le extension functions hanno overhead di prestazioni?

No, le extension functions vengono compilate come metodi statici. A livello di bytecode, chiamare una extension function è identico a chiamare un metodo statico con il ricevente come primo parametro. Nessuna riflessione o dispatch dinamico è coinvolto.

Si può dichiarare una extension property per una classe?

, le extension properties funzionano in modo simile alle extension functions ma non possono memorizzare stato — solo un getter e un setter. Ad esempio: val List.sum get() = reduce(Int::plus). Anch'esse vengono compilate come metodi getter/setter statici.

In cosa differiscono le extension functions dai metodi nelle classi di utilità Java?

In Java si scrive StringUtils.isEmail(str), mentre in Kotlin si scrive str.isEmail(). La differenza non è solo sintattica: le extension functions supportano l'autocompletamento nell'IDE, migliorano la leggibilità delle catene di chiamate e consentono all'IDE di suggerire funzioni pertinenti per un tipo specifico. Java non ha queste capacità.

Riepilogo

  • Extension function — un metodo con un tipo ricevente, chiamato come membro della classe senza ereditarietà
  • Dispatch statico — selezione della funzione in base al tipo statico, non al tipo di esecuzione
  • Zero overhead — compilata come metodo statico con il ricevente come primo parametro
  • Import obbligatorio per l'uso in altri file, alias tramite as supportato
  • I membri della classe hanno priorità sulle extension functions con la stessa firma
  • Member extensions — estensioni dichiarate all'interno di una classe hanno accesso ai suoi membri
  • Uso pratico — utilità per String, View, Context, collezioni e costruzione DSL

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche