Variance ◦ Covariance, contravariance, invariance • Declaring generic functions, properties, and classes • Variance ◦ Type projections ◦ Use-site vs declaration-site variance specification • Type erasure ◦ What it is ◦ How to get around it ◦ *- projections
parameter T and U is a subtype of T, then C<U> is a subtype of C<T> • U subtype of T ⇒ C<U> subtype of C<T> • Example: List<Int> is a subtype of List<Number> because Int is a subtype of Number. • Applies to types that are “producers”, or a “source” of T • T only appears only in “out” position, i.e., the return type of a function ◦ Example: getters • T is never in “in” position, i.e. the type of a function argument.
parameter T and U is a subtype of T, then C<T> is a subtype of C<U> • U subtype of T ⇒ C<T> subtype of C<U> • Example: Function1<Number, Int> is a subtype of Function1<Int, Int> because Int is a subtype of Number. • Applies to types that are “consumers” of T • T only appears only in “in” position, i.e., the type of a function argument • T is never in “out” position, i.e. the return type of a function.
T = U • Example: Array<T> is invariant in T • T appears in both “in position” and “out position” • Type is both a producer and consumer of T To remember: Lambdas are contra-variant in their argument types and covariant in their return type
for a super-type.” • “Annie get your gun”-principle ◦ Subtype to super-type: “Anything you can do, I can to better. I can do anything better than you!” • Example: If anything a List<Number> produces is OK, then anything a List<Integer> produces is OK too. • Example: Any input to a Function1<Int, Int> can be input to a Function1<Number, Int> too. • Example: An Array<Int> is better than an Array<Number> in the same sense that a List<Int> is better than a List<Number>, but an Array<Number> can hold anything an Array<Int> can hold. So neither is better than the other.
eager to go out to a restaurant, he asks the hotel clerk if there is a vending machine (VM) in the hotel where he can buy a chocolate bar. He also says he only has a few dollar bills to pay with, so the vending machine must accept dollar bills as payment. The hotel clerk gives Bob directions to the vending machine, and Bob heads to the VM. After seeing the VM, Bob is furious! He stomps back to the reception and complains: “I specifically asked for a VM that accepts dollar bills as payment, but that machine accepts coins, banknotes, credit cards, and what have you! Moreover, it has no selection for chocolate bar! KitKat, Snickers, chips and peanuts, yes, but chocolate bar? Nooo!” “Is there a problem?”, asks the bewildered hotel clerk.
library: <root url="jar://$USER_HOME$/jars/robot.jar!/" /> (see .idea/libraries/robot.xml). Copy this jar from https://github.com/jointheleague/Robot/blob/master/jar/robot.jar
T> that are in "out position" are replaced by Any? */ fun <T : Number> getFromInProjection(a: Array<in T>) { val b = a[0] } /** * All occurrences of T in Array<out T> that are in "in position" are replaced by Nothing */ fun <T : Number> insertIntoOutProjection(a: Array<out T>, b: T) { a[0] = b ⇒ Error!! (Would only work if b were of type Nothing :-) } • “T in in position” = “T is an argument type” • “T in out position” = “T is a return type”
subtype relationship between generic types ◦ Example: class GenericRobot<in T> declares that GenericRobot<RobotCommand> is a subtype of GenericRobot<PrimitiveCommand> (because RobotCommand is a supertype of PrimitiveCommand). ◦ “Once for all” declaration • Use-site variance ◦ Specifies which types can be assigned to a variable or function argument, without there being a subtype relationship between them ◦ Example: fun <T : RobotCommand> execute(robot: GenericRobot<in T>, command: T) {...} declares that when T is bound to PrimitiveCommand, robot can be of type GenericRobot<RobotCommand> ◦ Uses type projections (in this example, replaces all occurrences of T in out position in GenericRobot with Any?)
time ◦ Example: Compiler verifies and “knows” that an instance of List<String> only contains instances of String and does not contain null. ◦ Compiler assigns types to type parameters • During runtime, the information about which types have been assigned to type parameters is lost. • See code examples