Beispielfrage zu Vererbung vs Polymorphie

Zeboo

Lt. Commander
Registriert
Juli 2008
Beiträge
1.562
Hallo,

ich bin mir nicht sicher ob ich Polymorphie wirklich verstanden habe, deswegen würde ich gerne ein kleines Beispiel machen und ihr korrigiert mich falls das falsch sein sollte :)

Also es gibt Vererbung und Polymorphie. Bei der einfachen Vererbung kriegt mein das Objekt was von einem anderen Objekt (bzw. von eine Oberklasse) erbt die Eigenschaften. Bsp: Oberklasse Tier und Unterklasse Hund, Katze, Ente... alle diese Tiere haben von der Oberklasse "Tier" so einiges geerbt. Zum Beispiel sind alle von ihnen sterblich, alle von ihnen machen häufchen usw. ;)

Polymorphie aber bedeutet, dass obwohl diese abstrakt gesehen alle gleich sind bzw. gleiche Eigenschaften haben, sind die Methoden anders. Das heißt eine Katze sagt "Mau" und ein Hund sagt "Wuff" :)

Wäre das eine gute Erklärung zu Plymorphie? Ich weiß im Netz steht es professioneller, aber genau so will ich das nicht auswendig lernen.

Gruß
 
„Vielgestaltigkeit“ d.h. Methodennamen können für viele
verschiedene Methoden verwendet werden.

Durch Vererbung werden Attribute und Methoden der Basisklasse
(auch „Ableitung“) in der abgeleiteten Klasse wieder verwendet. Weitere Attribute
und Methoden können in der abgeleiteten Klasse hinzukommen. Die
abgeleitete Klasse wird angereichert („Methoden- und Attribute-
Vermehrung“).
(Erspart dem Programmierer das dauernde Wiederholen; gut für
steigende Produktivität. Gut gegen Redundanz.)
 
Zeboo schrieb:
Polymorphie aber bedeutet, dass obwohl diese abstrakt gesehen alle gleich sind bzw. gleiche Eigenschaften haben, sind die Methoden anders. Das heißt eine Katze sagt "Mau" und ein Hund sagt "Wuff" :)
Jein, für Polymorphie braucht man nicht zwangläufig ein Vererbung. Polymorphie bedeutet, dass das Ergebnis eines Ausdrucks von den verwendeten Typen abhängt und nicht vom Ausdruck selbst. Ein Beispiel, gegeben Sei "a + b": Wenn a und b ganze Zahlen sind, dann wird eine normale Addition durchgeführt. Wenn a und b Vektoren sind, werden die Komponenten des Vektors addiert. Streng genommen gibt es selbst in C Polymorphismus, so Bewirkt "a / b" bei zwei Integern eine Integer-Division, bei zwei Fließkommazahlen eine entsprechende Fließkomma-Division, auch wenn das viele vielleicht nicht so nennen würden.
 
Zuletzt bearbeitet:
die erklärung von vererbung passt ansich. es ist halt so wie im leben wie du geschrieben hast. es gibt bäume, davon gibt es laub- und nadelbäume (zwei vererbbare klassen vom "baum") und diese wiederum enthalten kiefer, fichte, buche usw. (wieder haufenweise vererbbare klassen von den zwei vorherigen). und jede nimmt halt die eigenschaften und methoden der oberklasse mit. bspw. sehen nadelbäume immer wie nadelbäume aus und laubbäume wie laubbäume. oder ein mensch erbt eigenschaften von vater und mutter. gibt zig weitere beispiele dafür...

Zeboo schrieb:
Wäre das eine gute Erklärung zu Plymorphie?
polymorphie bedeutet einfach, dass du für funktion/methode x unterschiedliche signaturen hast. bspw. im konstruktor (um mal bei objekten und deinem beispiel zu bleiben, ich verwende mal c++):
Code:
class Tier
{
  public :
    Tier( Tier &T );
    Tier( string TierName );
    Tier( int Anzahl );
};
das is zwar ein wenig zu vereinfacht gedacht, aber mehr beschreibt polymorphie nicht wirklich. halt dass du funktion x auf y unterschiedliche arten ansprechen kannst. in php gibt es z.b. keine polymorphie, wodurch du viele umständliche sachen zur prüfung vornehmen musst. bspw. hier eine klasse für einen farbwert (nur der konstruktor):
PHP:
public function __construct( $R = null, $G = null, $B = null, $A = self::ALPHA_OPAQUE )
{
  if( $R === null && $G === null && $B === null )
    $this->SetRGBA( 0, 0, 0, $A );
  else if( is_array( $R ) && $G === null && $B === null )
    $this->SetRGBAArray( $R );
  else if( is_int( $R ) && $G === null && $B === null )
    $this->SetRGBAInt( $R );
  else if( is_int( $R ) && is_int( $G ) && is_int( $B ) && is_int( $A ) )
    $this->SetRGBA( $R, $G, $B, $A );
  else if( is_string( $R ) && $G === null && $B === null && F\IsHexString( $R ) )
    $this->SetRGBAHex( $R );
  else if( is_string( $R ) && $G === null && $B === null &&
             (F\IsRGBString( $R ) || F\IsRGBAString( $R )) )
    $this->SetRGBAString( $R );
}
wie du siehst, ist es nicht wirklich elegant und übersichtlich. und schlecht wartbar obendrein auch noch. in c++ könnte man dies dank polymorphie sehr einfach und übersichtlich gestalten (ich behalte die reihenfolge der werte ein wie du sie oben sehen kannst):
Code:
RGBA() { SetRGBA( 0, 0, 0, 0 ); }
RGBA( int Values[] ) { SetRGBAArray( Values ); }
RGBA( int Color ) { SetRGBAInt( Color ); }
RGBA( int R, int G, int B, int A ) { SetRGBA( R, G, B, A ); }
RGBA( string Str )
{
  if( IsRGBString( Str ) || IsRGBAString( Str ) )
    SetRGBAString( Str );
  else if( IsHexString( Str ) )
    SetRGBAHex( Str );
}
daraus werden aber auch einschränkungen der polymorphie klar. heißt, dass du nicht eine funktion mit parametern des gleichen typs ausstatten kannst. z.b. siehst du im php-beispiel, dass einmal ein rgb-string und einmal ein hex-string übergeben wird. da beides strings sind, kannst du nicht folgendes schreiben:
Code:
RGBA( string Hex ) { SetHexString( Hex ); }
RGBA( string RGB ) { SetRGBString( RGB ); }
RGBA( string RGBA ) { SetRGBAString( RGBA ); }
hier können nämlich mehrere varianten zutreffen und dies wird normalerweise durch den compiler unterbunden. sowas ist z.b. auch unzulässig:
Code:
RGBA( int Red ) { SetRGBA( Red, 0, 0, 0 ); }
RGBA( int Green ) { SetRGBA( 0, Green, 0, 0 ); }
RGBA( int Blue ) { SetRGBA( 0, 0, Blue, 0 ); }
RGBA( int Alpha ) { SetRGBA( 0, 0, 0, Alpha ); }

ich hoffe ich konnte ein wenig licht ins dunkle bringen. :)
 
claW. schrieb:
polymorphie bedeutet einfach, dass du für funktion/methode x unterschiedliche signaturen hast. bspw. im konstruktor (um mal bei objekten und deinem beispiel zu bleiben, ich verwende mal c++):
Nein.
in php gibt es z.b. keine polymorphie, wodurch du viele umständliche sachen zur prüfung vornehmen musst. bspw. hier eine klasse für einen farbwert (nur der konstruktor):
Nein, man kann in PHP einfach nur keine Funktionsnamen überladen, was für eine dynamische Sprache nicht gerade verwunderlich ist. Das geht da höchst selten. Polymorphie funktioniert:
PHP:
<?php

class Test {
  function x() { echo "Test\n";  }
}

class Test2 {
  function x() { echo "Test2\n";  }
}

$array = array(new Test, new Test2);

foreach($array as $obj) {
  $obj->x(); // Geht.
}

?>
 
@Darii: Dein Beispiel ist aber (im Sinne der Polymorphie) auch nicht ganz korrekt dargestellt. Vielleicht hast du es auch einfach nur vergessen, so zu tippen.

Deine Klasse Test2 ist nicht von Test abgeleitet. In dem Fall von Polymorphie zu sprechen, passt nicht. Wenn Test2 von Test abgeleitet wäre, wäre das Beispiel i.O.
 
Cobinja schrieb:
@Darii: Dein Beispiel ist aber (im Sinne der Polymorphie) auch nicht ganz korrekt dargestellt. Vielleicht hast du es auch einfach nur vergessen, so zu tippen.

Deine Klasse Test2 ist nicht von Test abgeleitet. In dem Fall von Polymorphie zu sprechen, passt nicht. Wenn Test2 von Test abgeleitet wäre, wäre das Beispiel i.O.
Nein, das war volle Absicht. Für Polymorphie bedarf es keiner direkten „Verwandschaftsbeziehung“ das wollte ich damit nochmal verdeutlichen. Sieht man übrigens auch in Java, wo Polymorphie meist über Interfaces zu Tage tritt.
 
Darii schrieb:
Für Polymorphie bedarf es keiner direkten „Verwandschaftsbeziehung“ das wollte ich damit nochmal verdeutlichen.
Es gibt Sprachen, in denen für Polymorphie keine direkte Vererbungs-Verwandschaft bestehen muss. Die sind allerdings rar gesät. Ein Beispiel ist Objective-C.

Im traditionellen Sinne ist die Polymorphie allerdings eng an die Vererbung geknüpft.

Deswegen solltest du Beispiele von klassenübergreifender Polymorphie auch speziell so kennzeichnen, wenn jemand wie hier eine Verständnis-Frage stellt.

Und was Java angeht: Bei der Benutzung von Interfaces wird sehr wohl Vererbung verwendet. Man kann ein Interface als Klasse mit ausschließlich abstrakten Methoden sehen.
Es wird in Java zwar oft mit Interfaces gearbeitet, aber genauso gut kann man das gleiche mit abstrakten Klassen realisieren (was manchmal sogar der sinnvollere Weg ist, wenn man sich mit Generics beschäftigt (Das ist allerdings ein anderes Thema)).
 
Cobinja schrieb:
Es gibt Sprachen, in denen für Polymorphie keine direkte Vererbungs-Verwandschaft bestehen muss. Die sind allerdings rar gesät. Ein Beispiel ist Objective-C.
Ich weiß nicht wie du auf ObjC kommst, aber deine Wortwahl lässt darauf schließen, dass du das gerade in der Wikipedia gefunden hast. „klassenübergreifende“ Polymorphie ist jedenfalls alles andere als rar gesägt sondern in den meisten(allen?) Sprachen zu finden, die nicht statisch typisiert sind. Also PHP, Python, Ruby, Javascript, Smalltalk, etc. pp. Und in statisch typisierten Sprachen geht es nunmal schlecht anders.

Im traditionellen Sinne ist die Polymorphie allerdings eng an die Vererbung geknüpft.
Was ist für dich bitteschön traditionell? C++? Java? In der ersten rein objektorientierten Sprache (Smalltalk) war das jedenfalls auch nicht an Vererbung geknüpft und Smalltalk ist deutlich älter als C++ und Java.

Deswegen solltest du Beispiele von klassenübergreifender Polymorphie auch speziell so kennzeichnen, wenn jemand wie hier eine Verständnis-Frage stellt.
Gerade eine Verständnisfrage sollte so abstrakt wie möglich beantwortet werden und sich nicht an irgendwelchen Sprachen festmachen. Und es ist schlicht und ergreifen so, dass Polymorphie in vielen Sprachen etwas völlig triviales ist. Da muss man jetzt nicht noch irgendeinen Hokuspokus mit Vererbung hinzudichten, damit das möglichst kompliziert erscheint.

Und was Java angeht: Bei der Benutzung von Interfaces wird sehr wohl Vererbung verwendet. Man kann ein Interface als Klasse mit ausschließlich abstrakten Methoden sehen.
Man kann es auch lassen und ein Interface einfach als einen formalen Vertrag sehen mit dem man sich auf eine gemeinsame Schnittstelle einigt. Da brauche ich keine Klasse zu. Wie das dann konkret realisiert wird, ist ein Implementierungsdetail, das einem erstmal egal sein kann.
 
Zuletzt bearbeitet:
Mein letzter Post war inhaltlich nicht ganz korrekt. Dafür möchte ich mich hiermit entschuldigen. War mein Fehler.

Darii schrieb:
Ich weiß nicht wie du auf ObjC kommst, aber deine Wortwahl lässt darauf schließen, dass du das gerade in der Wikipedia gefunden hast.
Stimmt. Da sehe ich allerdings kein Problem mit.

Darii schrieb:
Gerade eine Verständnisfrage sollte so abstrakt wie möglich beantwortet werden und sich nicht an irgendwelchen Sprachen festmachen. Und es ist schlicht und ergreifen so, dass Polymorphie in vielen Sprachen etwas völlig triviales ist. Da muss man jetzt nicht noch irgendeinen Hokuspokus mit Vererbung hinzudichten, damit das möglichst kompliziert erscheint.
Ich habe es nicht an Sprachen festgemacht, sondern an Konzepten. Abgesehen davon will der Thread-Opener etwas lernen. Und da sollte man dann schon darauf hinweisen, wenn ein Sachverhalt für einen Anfänger nicht unbedingt auf den ersten Blick ersichtlich ist.

Darii schrieb:
Man kann es auch lassen und ein Interface einfach als einen formalen Vertrag sehen mit dem man sich auf eine gemeinsame Schnittstelle einigt.
Das finde ich nun wieder vielleicht nicht falsch, aber etwas ungenau. Der formale Vertrag steht m.E. weit vor dem, was einem eine verwendete Sprache dann zur Verfügung stellt.
Und ein "normales" Interface (keine Annotation) ist in Java nunmal etwas, mit dem man (fast) wie mit einer Klasse arbeiten kann (z.B. Typabfrage mit instanceof, Typecasting, ...). Vor allem aber sind Interfaces ein Mittel, um eine Art Mehrfachvererbung möglich zu machen, die es ansonsten in Java nicht gibt.
 
Zurück
Oben