Kotlin is oorspronkelijk ontworpen als een veilige en beknopte alternatieve taal voor Java. Een van de sterke punten is het ontwikkelde mechanisme voor type-afleiding, dat het mogelijk maakt om minder omslachtige code te schrijven zonder verlies van typezuiverheid. Type-afleiding is geïnspireerd door functionele talen (zoals Scala en Haskell), en ook door moderne trends in het ontwerpen van statisch getypeerde talen.
In Java en andere statische talen is het noodzakelijk om types expliciet aan te geven, wat leidt tot overbodige code. Echter, het ontbreken van expliciete types kan het begrip van de code bemoeilijken en leiden tot onduidelijke fouten als de type-afleiding niet correct werkt.
In Kotlin kan de compiler vaak het type van een variabele of expressie zelfstandig bepalen op basis van de context. Dit werkt voor variabelen, return types van functies en binnen expressies met lambda’s. Er zijn echter situaties waarin de compiler vereist dat het type expliciet wordt aangegeven — bijvoorbeeld bij het declareren van een functie zonder returntype binnen een klasse ('fun doSomething()') of wanneer expressies ambigu zijn.
Voorbeeld code:
val a = 42 // Int val s = "hello" // String fun sum(x: Int, y: Int) = x + y // return type Int wordt automatisch afgeleid val list = listOf(1, 2, 3) // List<Int> // Expliciete type-aanduiding is nodig als de waarde niet kan worden afgeleid val emptyList: List<String> = emptyList() // anders wordt het List<Nothing>
Belangrijkste kenmerken:
Waarom kan men het type na het dubbele punt niet altijd weglaten, bijvoorbeeld voor klasse-eigenschappen?
Voor eigenschappen die niet op het moment van declaratie zijn geïnitialiseerd (bijvoorbeeld via een getter of in een init-blok), kan de compiler het type niet automatisch afleiden omdat hij de initializer niet ziet.
class User { val fullName: String // Type moet expliciet worden aangegeven, anders fout get() = "name" }
Wat voor type heeft een variabele als je emptyList() gebruikt zonder expliciete type-aanduiding?
Er wordt het type List<Nothing> afgeleid, wat het resultaat bijna onbruikbaar maakt.
val list = emptyList() // List<Nothing>
Wanneer werkt type-afleiding niet met functiepuntparameters?
In de handtekening van een functie moet altijd expliciet het type van parameters worden aangegeven, anders geeft de compiler een foutmelding.
// Fout: // fun foo(x) = x * 2 // Juist: fun foo(x: Int) = x * 2
Een ontwikkelaar gebruikt emptyList() om een waarde uit een API-functie te retourneren zonder expliciete type-aanduiding. Het resultaat is het type List<Nothing>, wat problemen veroorzaakt bij het werken met deze API.
Voordelen:
Een ontwikkelaar geeft altijd expliciet het type aan bij het werken met lege verzamelingen en waar dit de leesbaarheid verbetert, en vertrouwt in andere gevallen op de type-afleiding van de compiler.
Voordelen: