问题
In the FP in Scala course, Martin mentions, the arguments are "contravariant" while the return types are "covariant". I don't think I understood that completely - can someone help with this one?
回答1:
Assume Bonobo extends Animal and you have a function foo of type Animal => Bonobo. In some other place you have a variable bar of type Bonobo => Animal. Should you be allowed to assign foo to bar? Sure:
fooexpects just an animal as argument (which is "too wide" or "too general" compared to the expected argument typeBonoboofbar, hence contravariant), but it has no problem processing a bonobo.- you get a bonobo back from
foo(which is "too narrow" or "too special" compared to the expected return typeAnimalofbar, hence covariant), but this is fine, as the caller ofbarexpects to deal with all kinds of animals
But you can't turn the example around, you can't assign a Bonobo => Animal function where an Animal => Bonobo function is expected, as the argument doesn't fit (it might get an animal that isn't a bonobo), and the return type is wrong either (you need a bonobo back, but get an animal, which could be something different).
This is true for all function-like things (e.g. methods): It doesn't matter if argument types are more general and return types are be more special than expected. "Contravariant" and "covariant" is just fancy terminology for this simple fact.
来源:https://stackoverflow.com/questions/26360259/scala-arguments-contravariant-and-return-types-are-covariant-why