I know about using co- and contravariance in the standard library (e.g. collections and trait Function) I wonder how co- and contravariance are used in design of "real world" business applications.
The classic example is functions, taking the Scala interface for a function with a single argument:
trait Function1[-T1, +R]
Which is contravariant (the -) for the argument, and covariant (the +) for the return type.
Why?
Imagine you have these classes:
class Timelord { ... }
class Doctor extends Timelord { ... }
class Enemy { ... }
class Dalek extends Enemy { ... }
If you have a method that takes, as a parameter, a Doctor => Enemy function; then it's okay to supply an instance of TimeLord => Enemy. It'll still accept instances of Doctor.
So TimeLord => Enemy is a subclass of Doctor => Enemy because TimeLord is a superclass of Doctor, it's contravariant in that parameter.
Likewise, a function returning a Dalek is valid when you need a function returning some Enemy, because a Dalek is-an Enemy
So Doctor => Dalek is a subclass of Doctor => Enemy because Dalek is a subclass of Enemy, it's covariant in that parameter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With