article banner

Exercise: Generic Consumer

In your project, you use a class that represents a consumer of some type. You have two implementations of this class: Printer and Sender. A printer that can accept Number should also accept Int and Double. A sender that can accept Int should also accept Number and Any. In general, a consumer that can accept T should also accept S if it is a subtype of T. Update the Consumer, Printer and Sender classes to achieve this.

abstract class Consumer<T> { abstract fun consume(elem: T) } class Printer<T> : Consumer<T>() { override fun consume(elem: T) { // ... } } class Sender<T> : Consumer<T>() { override fun consume(elem: T) { // ... } }

Example usage:

val p1 = Printer<Number>() val p2: Printer<Int> = p1 val p3: Printer<Double> = p1 val s1 = Sender<Any>() val s2: Sender<Int> = s1 val s3: Sender<String> = s1 val c1: Consumer<Number> = p1 val c2: Consumer<Int> = p1 val c3: Consumer<Double> = p1

This problem can either be solved in the below playground or you can clone kotlin-exercises project and solve it locally. In the project, you can find code template for this exercise in advanced/generics/Consumer.kt. You can find there starting code and example usage.

Once you are done with the exercise, you can check your solution here.

Playground

abstract class Consumer<T> { abstract fun consume(elem: T) } class Printer<T> : Consumer<T>() { override fun consume(elem: T) { // ... } } class Sender<T> : Consumer<T>() { override fun consume(elem: T) { // ... } } fun main(args: Array<String>) { val p1 = Printer<Number>() val p2: Printer<Int> = p1 val p3: Printer<Double> = p1 val s1 = Sender<Any>() val s2: Sender<Int> = s1 val s3: Sender<String> = s1 val c1: Consumer<Number> = p1 val c2: Consumer<Int> = p1 val c3: Consumer<Double> = p1 }