Diese Frage ist alt, aber ich denke, eine klarere Erklärung ist, das Liskow-Substitutionsprinzip aufzurufen: Alles, was an einer Oberklasse wahr ist, sollte für alle Unterklassen gelten. Du solltest in der Lage sein, mit einem SubFoo alles zu tun, was du mit einem Foo machen kannst, und vielleicht mehr.
Angenommen, wir haben Calico <: Katze <: Tier, und Husky <: Hund <: Tier. Lassen Sie uns einen Function[Cat, Dog]
ansehen. Welche Aussagen treffen darauf zu? Es gibt zwei:
(1) Sie in jeder Katze passieren kann (so dass jede Unterklasse von Cat)
(2) Sie können auf dem Rückgabewert jeder Hund Methode aufrufen
So macht Function[Calico, Dog] <: Function[Cat, Dog]
Sinn ? Nein, Aussagen, die für die Oberklasse gelten, gelten nicht für die Unterklasse, nämlich Anweisung (1). Du kannst keine Katze an eine Funktion weitergeben, die nur Kaliko-Katzen aufnimmt.
Aber macht Sinn? Ja, alle Aussagen zur Oberklasse gelten für die Unterklasse. Ich kann immer noch eine Katze reinlassen - in der Tat kann ich noch mehr als das, ich kann jedes Tier übergeben - und ich kann alle Dog-Methoden auf den zurückgegebenen Wert aufrufen.
So A <: B
impliziert Function[B, _] <: Function[A, _]
Nun tut Function[Cat, Husky] <: Function[Cat, Dog]
Sinn? Ja, alle Aussagen über die Oberklasse gelten für die Unterklasse; Ich kann immer noch eine Katze einreichen, und ich kann immer noch alle Dog-Methoden auf den zurückgegebenen Wert aufrufen - in der Tat kann ich noch mehr als das tun, ich kann alle Husky-Methoden auf den zurückgegebenen Wert aufrufen.
Aber macht Function[Cat, Animal] <: Function[Cat, Dog]
Sinn? Nein, Aussagen, die für die Oberklasse wahr sind, gelten nicht für die Unterklasse, nämlich die Aussage (2). Ich kann nicht alle auf Dog verfügbaren Methoden auf dem zurückgegebenen Wert aufrufen, nur die auf Animal verfügbaren.
Also mit einem Function[Animal, Husky]
kann ich alles tun, was ich mit einem Function[Cat, Dog]
tun kann: Ich kann in jedem Cat übergeben, und ich kann alle Dog-Methoden auf den zurückgegebenen Wert aufrufen. Und ich kann noch mehr tun: Ich kann andere Tiere weitergeben, und ich kann die auf Husky verfügbaren Methoden aufrufen, die bei Dog nicht verfügbar sind. Also macht es Sinn: Function[Animal, Husky] <: Function[Cat, Dog]
. Der erste Typparameter kann durch eine Superklasse ersetzt werden, der zweite durch eine Subklasse.
Danke, das war sehr klar. Versuch, (neu) zu definieren: "Co/Kontra-Varianz sind Eigenschaften, die die Subtyprelation zwischen Typen vorgeben, abhängig von der Art derselben Beziehung zwischen ihren Komponententypen". Abstrakt, ich weiß, aber ich bevorzuge eine Definition ohne Beispiele (obwohl Ihre sehr hilfreich war). – bjt38
danke für die -A, könntest du erklären warum ist + B in der Funktion1 [-A, + B] – liango
@liango - Eine Erklärung mit einem Beispiel: Wenn du eine 'String' zurückgibst, gibst du sicher ein' Object' zurück, also '. .. => String' muss eine Unterklasse von '... => Object' sein. Das bedeutet "+ B". –