| 

.NET C# Java Javascript Exception

7
Kovarianz:
Ist mit der Vererbungshierarchie.
Kontravarianz:
Ist entgegen der Vererbungshierarchie.

Nun gilt bei Java und C#:
Rückgabewerte sind Kovariant weil folgendes gilt:
static Hund MakeHund() { ...
Func<Tier> func = MakeHund();

Hier wird nun ein Hund in ein Tier geschrieben. Compiliert auf jedenfall. Nun die Frage wenn ich den Hund in ein Tier reinspeichere ist das doch Entgegen der Vererbungshierarchie? Was bedeuten würde es ist Kontravariant.

Parameter sind Kontravariant weil folgendes gilt:
void Foo(Tier t) {...
Action<Hund> action = Foo;

Nun wird ein Hund übergeben und ein Tier erwartet. Entgegen der Vererbungshierarchie -> Kontravariant. Stimmt also.

Irgendetwas übersehe ich wohl, könnte mir jemand helfen?
News:
05.08.2009
Mammal 195 2 6
2 Antworten
13
Grundsätzlich geht es bei Ko- und Kontravarianz um die Kompatibilität von Ein- und Rückgabewerten.

Durch Polymorphie kann - einfach ausgedrückt - ein Typ in verschiedener Gestalt auftreten.

Weiters sind Delegaten als Funktionszeiger zu verstehen die stark typisiert sind.

Da abgeleitete Typen auch Typen der jeweiligen Basisklasse sind (Polymorphie) können Delegaten die als Rückgabetyp den Basistyp erwarten auch auf Methoden zeigen die einen abgeleiteten Typ zurückgeben (Kovarianz) - dabei wird die Vererbungshierarchie nicht verletzt.

Delegaten die als Argument einen abgeleiteten Typ erwarten können auch auf Methoden zeigen welche als Argument den Basistyp erwarten (Kontravarianz) - auch hier wird die Vererbungshierarchie nicht verletzt.

Wie von dir richtig festgestellt ist Kovarianz mit der Vererbungsrichtung und Kontravarianz entgegen der Vererbungsrichtung.

Ich würde nicht allzu viel Wert auf korrekte Bezeichnungen legen sonder mehr auf das Verständnis "wie was" funktioniert. Die Bezeichnungen für das "wie was" sind meiner Meinung nach nur dazu da dass ein "Kind einen Namen hat" und derjenige der zum ersten Mal dies veröffentlicht mehr oder weniger Ruhm hat.

Aber genug der Worte. Folgend Beispiele in C# die den Sachverhalt klären versuchen.

Kovarianz
using System;

namespace Kovarianz_Kontravarianz
{
class Kovarianz
{
// Delegat für eine Methode die als Rückgabewert FooBase erwartet.
delegate FooBase Creator();
//---------------------------------------------------------------------
static void Main()
{
// Normale Verwendung des Delegaten:
Creator fooBaseCreator = CreateFooBase;

// Verwendung des Delegaten mit Kovarianz:
// Der tatsächliche Rückgabetyp der Methode Foo erbt vom Typen
// FooBase den der Delegat erwartet. Somit gilt:
// Typ: Foo -> FooBase
// Rückgabetyp: Foo -> FooBase
// Beide Vererbungsrichtungen sind in die selbe Richtung und
// somit kovariant.
Creator fooCreator = CreateFoo;

// Aufrufen der Delegaten:
FooBase object1 = fooBaseCreator();
FooBase object2 = fooCreator();

// Kontrollausgabe um zu sehen welche Typen erzeugt wurden:
Console.WriteLine(object1.GetType().Name);
Console.WriteLine(object2.GetType().Name);
Console.ReadKey();
}
//---------------------------------------------------------------------
// Erzeugt eine Basisklasse.
static FooBase CreateFooBase() { return new FooBase(); }
//---------------------------------------------------------------------
// Erzeugt einen von der Basisklasse abgeleiteten Typ.
static Foo CreateFoo() { return new Foo(); }
}
//-------------------------------------------------------------------------
class FooBase { }
//-------------------------------------------------------------------------
class Foo : FooBase { }
}


Kontravarianz
using System;

namespace Kovarianz_Kontravarianz
{
class Kovarianz
{
// Delegat für eine Methode mit einem Argument vom Typ FooBase.
delegate void DoSomethingWithFooBase(FooBase o);

// Delegat für eine Methode mit einem Argument vom Typ Foo.
delegate void DoSomethingWithFoo(Foo o);
//---------------------------------------------------------------------
static void Main()
{
// Normale Verwendung des Delegaten:
DoSomethingWithFooBase printTypeOfFooBase = PrintType;

// Verwendung des Delegaten mit Kontravarianz:
// Der von der Methode erwartete Typ des Arguments ist FooBase
// und der vom Delegaten deklarierte Typ ist Foo welcher von FooBase
// erbt. Somit gilt:
// Typ: Foo -> FooBase
// Argument-Typ: FooBase <- Foo
DoSomethingWithFoo printTypeOfFoo = PrintType;

// Aufrufen der Delegaten:
printTypeOfFooBase(new FooBase());
//printTypeOfFooBase(new Foo()); // ist auch möglich
printTypeOfFoo(new Foo());

Console.ReadKey();
}
//---------------------------------------------------------------------
// Gibt des Typ.
static void PrintType(FooBase o)
{
Console.WriteLine(o.GetType().Name);
}
}
//-------------------------------------------------------------------------
class FooBase { }
//-------------------------------------------------------------------------
class Foo : FooBase { }
}


Hoffe es kann dir helfen.
06.08.2009
gfoidl 9,4k 3 5
1
Wow! Danke.
Mammal 06.08.2009
1
Genau, das ist die Qualität von Antwort die man braucht : )
Vielen Dank dafür!
07.08.2009
Mario Priebe 6,0k 3 9
1
Danke für die Blumen. Werde aber nicht jede Frage so ausführlich beantworten können ;)
Hier fand ich es angebracht um das Verständnisproblem zu lösen.
gfoidl 08.08.2009

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH