Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Quick Intro To Kotlin Generics

Quick Intro To Kotlin Generics

Covers how to work with generics from functions to classes ,type projections,generic constraints and type erasure

David Odari

October 05, 2019
Tweet

More Decks by David Odari

Other Decks in Programming

Transcript

  1. Generics Generic programming is a style of computer programming in

    which algorithms are written in terms of types to-be-specified-later that are then instantiated when needed for specific types provided as parameters. ~Wikipedia
  2. Example : class FishPlate { fun addFishToPlate(fish: Fish) {} }

    class UgaliPlate { fun addUgaliToPlate(ugali: Ugali) {} } class VeggiesPlate { fun addVeggiesToPlate(veggies: Veggies) {} }
  3. Example : class Ugali : Food class Veggies : Food

    class Fish : Food class Plate<T> { fun addFoodToPlate(vararg food: T) { } fun get() : T? = null }
  4. Example : object ServingRepo : IGetPlates { override fun getUgaliPlate()

    : Plate<Ugali> = Plate() override fun getFishPlate() : Plate<Fish> = Plate() override fun getVeggiesPlate() : Plate<Veggies> = Plate() }
  5. Generic Constraint class Plate<T : Food> { fun addFoodToPlate(vararg food:

    T) {} } //val plate: Plate<Int> = Plate() -> Won’t Compile val plate:Plate<Ugali> = Plate()
  6. Multiple Generic Constraints fun <T> T.cool() where T : Food,

    T : Edible { } class Medicine<T> where T : Tablet, T : Syrup { }
  7. Type Inference class Plate<T : Food>(food:T) { fun addFoodToPlate(vararg food:

    T) {} } val plate = Plate<Ugali>(Ugali()) val plate = Plate(Ugali())
  8. Variance Variance refers to how subtyping between more complex types

    relates to subtyping between their components.
  9. Invariance val numberList: List<Number> = mutableListOf() // val integerList: List<Int>

    = numberList -> Won't work Why? Take the numberList and add a double numberList.add(5.0) This does not correspond to the integer list and does not assure type safety
  10. Site Variance In Kotlin There are variance annotations that define

    variance on a type parameter They are In and Out. When provided at the type parameter declaration site, where the generic type is declared, they are referred to as declaration-site variance. Else,when the annotation is not placed where the type is declared, but where the type is used.It’s use-site variance.
  11. Example Declaration Site class Foo<in T>{} class Bar<out T>{} Use

    Site val arrayOfSomething: Array<in Any> = ... val arrayOfSomethingElse: Array<out Any> = ...
  12. Covariance Subtyping relation of the simple types are preserved for

    the complex types. E.g val ugaliList = mutableListOf<Ugali>() val foodList:List<Food> = ugaliList
  13. Covariance class OrdersCovariant<out T> { fun process(): T? = null

    } val covariantOrder: OrdersCovariant<Food> = OrdersCovariant<Fish>()
  14. Contravariance Enables you to use a more generic (less derived)

    type than originally specified. The specified type or its supertype. Example: //List is Invariant val numberList:List<Number> = mutableListOf() //val genericList: List<Int> = numberList → Won’t Compile
  15. Example class OrdersContravariant<in T> { fun process(t: T) {} }

    val contravariantOrder: OrdersContravariant<Fish> = OrdersContravariant<Food>()
  16. A type projection is a type that has been limited

    in certain ways in order to gain variance characteristics using use site variance.
  17. val arrayOfSomething: Array<in Food> = arrayOf() arrayOfSomething[0] = Fish() //We

    can’t call those methods that consume the type parameter val arrayOfSomethingElse: Array<out Food> = arrayOf() // arrayOfSomethingElse[0] = Fish() --> Won't Compile arrayOfSomething[0] Example:
  18. They come in handy when know nothing about the type

    argument, but need to use them in a safe way. The safe way here is to define such a projection of the generic type, that every concrete instantiation of that generic type would be a subtype of that projection. ~From Docs Star Projection:
  19. The type safety checks that Kotlin performs for generic declaration

    usages are only done at compile time. At runtime, the instances of generic types do not hold any information about their actual type arguments. Enforcing type constraints only at compile time and discarding the element type information at runtime. The type information is said to be erased.