Ich habe gerade erfahren, Scala. Jetzt bin ich verwirrt über Kontravarianz und Kovarianz.Kontra vs Kovarianz in Scala
Von diesen page lernte ich etwas unter:
Kovarianzstrukturen
Vielleicht ist das auffälligste Merkmal von Subtyping ist die Fähigkeit, einen Wert eines größeren Typs mit einem Wert einer engeren Art in einem Ausdruck zu ersetzen, . Angenommen, ich habe einige Arten Real
, Integer <: Real
, und einigen nicht verwandten Typen Boolean
. Ich kann eine Funktion is_positive :: Real -> Boolean
definieren, die auf Real
Werten funktioniert, aber ich kann diese Funktion auch auf Werte des Typs Integer
(oder eines anderen Subtyps von Real
) anwenden. Dieser Ersatz von breiteren (Vorfahren-) Typen durch schmalere (abgeleitete) Typen heißt covariance
. Das Konzept von covariance
ermöglicht es uns, generischen Code zu schreiben und ist von unschätzbarem Wert, wenn es um Vererbung in objektorientierten Programmiersprachen und Polymorphie in funktionalen Sprachen geht.
Aber ich sah auch etwas von woanders:
scala> class Animal
defined class Animal
scala> class Dog extends Animal
defined class Dog
scala> class Beagle extends Dog
defined class Beagle
scala> def foo(x: List[Dog]) = x
foo: (x: List[Dog])List[Dog] // Given a List[Dog], just returns it
scala> val an: List[Animal] = foo(List(new Beagle))
an: List[Animal] = List([email protected])
Parameter x
von foo
ist contravariant
; es erwartet ein Argument vom Typ List[Dog]
, aber wir geben es eine List[Beagle]
, und das ist in Ordnung
[Was ich denke, ist das zweite Beispiel sollte auch Covariance
beweisen. Weil ich aus dem ersten Beispiel gelernt habe, dass "diese Funktion auf Werte vom Typ Integer
(oder einem anderen Subtyp von Real
) angewendet wird". Entsprechend verwenden wir diese Funktion hier auf Werte vom Typ List[Beagle]
(oder einen anderen Subtyp von List[Dog]
). Aber zu meiner Überraschung erweist sich das zweite Beispiel Cotravariance
]
Ich denke, zwei die gleiche Sache sprechen, aber man beweist Covariance
und die anderen Contravariance
. Ich sah auch this question from SO. Aber ich bin immer noch verwirrt. Habe ich etwas übersehen oder ist eines der Beispiele falsch?
Gute Erklärung. Der Rückgabetyp von 'groomAnyAnimal' sollte' Dog' sein, um ihn zu verbinden, da Funktionen in ihrem Rückgabetyp und in ihrem Argumenttyp nur kovariant sind. –
@stew also denkst du, dass die Aussagen des zweiten Beispiels irgendwie falsch sind? – CSnerd
@CSnerd In Ihrem zweiten Beispiel möchten Sie irgendwie eine Aussage darüber machen, ob 'x' kovariant oder kontravariant ist. Wie bereits erwähnt, hat die Varianz jedoch nichts damit zu tun, ob Sie einen Subtyp übergeben können, für den ein Supertyp erforderlich ist (siehe [Loskow-Substitutionsprinzip] (http://en.wikipedia.org/wiki/Liskov_substitution_principle)). Das einzige, was in Ihrem zweiten Beispiel kovariant ist, ist 'List', daher ist' List [Beagle] 'ein Untertyp von' List [Dog] '. –