Laden...

Polymorphie: Was für ein Objekt erzeugt ClassA Instanz = new ClassB();?

12 Antworten
1,660 Aufrufe
Letzter Beitrag: vor 15 Jahren
Polymorphie: Was für ein Objekt erzeugt ClassA Instanz = new ClassB();?

Hallo!

Meine Frage ist vielleicht nicht so schwer zu beantworten, aber ich habe trotzdem große Probleme damit, für das ganze Formulierungen zu finden.
Eigentlich geht es um Java, aber ich glaube, diesbezüglich sind die Sprachen identisch.

Also, ich habe also eine Klasse ClassA und eine davon abgeleitete Klasse ClassB, beide enthalten die Methode X, B implementiert aber zusätzlich noch Y.

Jetzt fängt das Formulierungsproblem schon an:

ClassA Instanz = new ClassB();

Was erzeuge ich denn jetzt eigentlich, ein Objekt vom Typ A oder B? Ich habe jetzt natürlich schon den ein oder anderen Testlauf gestartet.

Das Objekt Instanz stellt nach außen hin nur Methoden bereit, die in ClassA auch enthalten sind. Das ist ja nicht verwunderlich, das ist ja der Kernpunkt der ganzen Sache.
ABER: eigentlich ist es doch schon ein Objekt vom Typ B.
Denn: zwar kann ich nicht Instanz.Y() aufrufen, da diese Methode in A nicht existiert. Sehr wohl kann ich auf Instanz aber X() aufrufen. Wenn ich X in B so überschreibe, dass intern die Methode Y() aufgerufen wird, so kann ich mit Instanz.X() ja doch indirekt auf Y() zugreifen, auch wenn es Y() in A gar nicht gibt.

Kann man sagen dass Instanz ein Objekt vom Typ B ist, dass nach außen aber "kastriert" wurde und eben nur die Methoden anbietet, die A ebenfalls besitzt?
also es hat da die komplette Funktionalität von B, nur eben nicht, wenn man von außen zugreifen will... oder sehe ich das falsch?

Also nicht, dass ich mich nicht damit befasst hätte. Den Haupteinsatzzweck habe ich denke ich schon verstanden. Beispiel:

Ich habe eine Klasse, welche die Methode Update() anbietet. Alle Kindklassen kann man jetzt in ein Array des Typs der Mutterklasse stecken und hat die Sicherheit, dass beim durchiterieren auf jedem Kindobjekt die Methode Update() existiert.
Eventuell wären da Interfaces besser, aber geht jetzt ja nur ums Prinzip.

Kurz gesagt weiß ich einfach nicht, als was ich das Objekt "Instanz" von oben betrachten soll. Nur vom Typ A kann es nicht sein, dann könnte ich ja auch gleich A instantiieren und bräuchte B garnicht. B kann es auch nicht sein, zumindest nicht vollwertig - denn der Zugriff von außen ist auf die Member von A beschränkt. Aber irgendwie doch eher B als A...

Ich hoffe, ihr versteh twas ich meine und könnt etwas Licht ins Dunkel bringen. Danke!

Also ich hoffe ich kann es einigermaßen verständlich und hoffentlich auch richtig erklären. Wenn ich unsinn erzähle so hoffe ich wird mich jemand anderes korrigieren aber es sieht aus meiner Sicher folgendermaßen aus.

Zunächst unterscheide ich zwischen Instanz und Objekt.

Objekt ist aus meiner Sicht eine formale Beschreibung von etwas. Sieh es als eine Art Bauanleitung für etwas. Das ist die Klasse die du schreibst , sie ist deine InstanzBauAnleitung

Eine Instanz hingegen ist die konkrete Ausprägung eines Objektes. Also quasi wie als wenn man das was auf der Bauanleitung steht gebaut hat.

Dein Beispiel :

ClassA Instanz = new ClassB();

Was in diesem Moment passiert, ist mMn. folgendes. Du instanzierst das Objekt ClassB und somit wird dieses auch genauso erzeugt wie in deiner Klasse ClassB beschrieben und nicht wie du meintest "kastriert". Das einzige was du jedoch machst ist, das du es in ein Referenzobjekt von ClassA zu packen, welche eine Elternklasse von ClassB darstellt.
D.h. nach außen hin wird sie lediglich als ClassA Objekt dargestellt jedoch ist sie intern immernoch ein Objekt vom Typ ClassB. Daher könntest du auch ohne weiteres mittels eines Casts Methoden aufrufen die nur in ClassB vorhanden sind. Das geht aber natürlich nur wenn sich in der Instanz auch wirklich ein Objekt vom Typ ClassB befindet.

((ClassB) Instanz).MeineMethodeDieNurInClassBIst

Ich hoffe das konnte deine Frage ein bisschen beantworten

Ein Objekt ist eine Instanz einer Klasse (oder struct), der Bauplan ist hierbei die Klassen(struct)Definition.

ClassA Instanz = new ClassB();

Instanz ist hierbei eine ClassB, nach außen aber nur eine ClassA; d.h. man kann nur Methoden benutzen, die die Klassendefinition von ClassA bietet. Wenn man nun sowas hat:

public class A 
{
   public virtual void Update()
   {
       return;
   }
}

public class B : A
{
    private void DoStuff()
    {
        //stuff
    }
    
    public override void Update()
    {
       this.DoStuff();
       base.Update();
    }
}

Und dann wie oben

A Instanz = new B();
Instanz.Update();

wird aber die Methode von B ausgeführt, da die Methode in A überschrieben ist.

Hallo Phelio,

Was erzeuge ich denn jetzt eigentlich, ein Objekt vom Typ A oder B?

ein Objekt vom Typ B. Immerhin heißt es ja auch new B. Die Zuweisung, die nach der Erzeugung erfolgt, ist ein separater Schritt, hat mit der Erzeugung also nichts zu tun und ist der eigentliche Akt der Polymorphie.

Ich rede im folgenden über Referenztypen.

Du musst zwischen Variable und Objekt und zwischen statischem Typ und dynamischen Typ unterscheiden.

Eine Variable ist etwas ganz anderes als ein Objekt. Eine Variable enthält nur eine Referenz auf das Objekt. Deshalb kann genauso gut eine Variable vom Typ A als auch eine Variable vom Typ B auf ein und dasselbe Objekt verweisen und das auch zur selben Zeit. Das Objekt bleibt immer dasselbe. Es ändert sich nicht dadurch, dass man einer Variable eine Referenz auf das Objekt zuweist.

Der statische Typ ist der Typ der Variable, der dynamische Typ ist der Typ des Objekts (auf das die Variable verweist). Statischer Typ und dynamischer Typ müssen aufgrund der Polymorphie nicht übereinstimmen.

Über eine Variable vom Typ A, die auf ein Objekt vom Typ B verweist, kann man natürlich nicht auf die spezifischen Methoden von B zugreifen, weil man ja - eben aufgrund der Polymorphie - zur Laufzeit im Allgemeinen nicht sicher sein kann, dass tatsächlich auf ein Objekt vom Typ B verwiesen wird. Deshalb kann man nur die Methoden aufrufen, die sicher existieren und das sind die vom Typ A.

Ansonsten stimmt deine Analyse. Insbesondere zeigt die Tatsache, dass man indirekt eben doch Y aufrufen kann, dass es kein Nachteil sein muss, dass man direkt nur auf die Methoden von A zugreifen kann.

Hallo KroaX,

Zunächst unterscheide ich zwischen Instanz und Objekt.

die Begriffe Instanz und Objekt sind Synonyme und können an (fast) allen Stellen im Text ausgetauscht werden, ohne dass dadurch die Bedeutung geändert wird. Die Unterscheidung, die du beschreibst, ist die zwischen Klasse und Objekt(=Instanz) und nicht die zwischen Objekt und Instanz.

herbivore

Hallo,

@Femaref: Du hast einen Fehler im Quellcode, du musst in A Update virtual deklarieren, sonst findet in C# keine polymorphie stadt.
@KroaX: Richtig böser fehler. Objekt ist ein synonym für Instanz! Das ist ganz wichtig und darf nicht verwechselt werden. Die Klasse (oder der Typ) stellen den Bauplan dar.
@Phelio: Um dein Beispiel mal auf den Punkt zu Bringen: Die Instanz von der Klasse ClassB wird in deinem Quellcode als Instanz von ClassA behandelt. Das geht, weil ClassB von ClassA erbt. Die Instanz hat immer noch den Zustand (Attribute, Properties, etc.) und das Verahlten (Methoden, etc.) von ClassB, der "Client"-Quellcode erwaretet jedoch nur das Verhalten und den Zustand eines ClassA Objektes, weshalb auch nichts anderes erwartet (also von Intelisense vorgeschlagen und vom Compiler aktzeptiert). Das da jetzt noch mehr drin steckt interesiert den "Client"-Quellcode nicht, ist also Gekapselt bzw. Geheimgehalten.

Noch Fragen?

Gruß
Juy Juka

[EDIT]Ach nö, herbivore war schneller als ich.[/EDIT]

Zunächst unterscheide ich zwischen Instanz und Objekt.
die Begriffe Instanz und Objekt sind Synonyme und können an (fast) allen Stellen im Text ausgetauscht werden, ohne dass dadurch die Bedeutung geändert wird. Die Unterscheidung, die du beschreibst, ist die zwischen Klasse und Objekt(=Instanz) und nicht die zwischen Objekt und Instanz.

Hello

Ja mir ist es gestern im Bett auch nochmal aufgefallen, eigentlich habe ich mir sogar noch im selben Satz widersprochen da ich erst von Objekt und dann von Klasse gesprochen hab 😄

Was ich meinte war natürlich das die Klasse die eigentliche Hülle ist und die Instanz oder das Objekt die Ausprägung.

Hast Recht Juy, hab den Code ohne Compiler geschrieben 😉

Vielleicht auch noch wichtig zu erwähnen:

Was du nicht machen kannst wäre


ClassB instanz = new ClassA();

Da gibt dir der Compiler einen Fehler. Was auch logisch ist da ClassA ja nicht alle Methoden, Properties,... von ClassB unterstützt!

Außerdem, außgehend von Femaref's code:
Wenn du


ClassA instanz = new ClassB();
instanz.Update();

ausführst, werden beide Methoden (sowohl von ClassA als auch von ClassB) ausgeführt. Grund dafür ist base.Update()! Mit "base" kann man auf die "Vater"-Klasse zugreifen. Wenn du soetwas verhindern möchtest muss die Methode im Vater "abstract" sein.

LG


ClassA instanz = new ClassB();

ClassB instanzB = instanz as ClassB();

Durch einen Cast hat man dann auch wieder "vollen" Zugriff auf die abgeleitete Klasse.

ClassA Instanz = new ClassB();

Was erzeuge ich denn jetzt eigentlich, ein Objekt vom Typ A oder B? Ich habe jetzt natürlich schon den ein oder anderen Testlauf gestartet.

Du hast ein Objekt vom Typ ClassA, welches aber ohne das Werfen einer Exception auf ClassB gecastet werden kann. D. h. ohne Cast ist die Methode Y nicht verfügbar, sondern nur die Methode X.

Kann man sagen dass Instanz ein Objekt vom Typ B ist, dass nach außen aber "kastriert" wurde und eben nur die Methoden anbietet, die A ebenfalls besitzt?

Das kann man so wahrscheinlich nicht sagen (Informatiker der reinen Lehre, wo seid Ihr?), aber es läuft zumindest darauf hinaus.

Aber irgendwie doch eher B als A...

Bau Dir entsprechenden Interfaces. Dann kannst Du mit IWasIchBraucheVonB Instanz = new ClassB das erreichen, was Dir vorschweb.

Hinrich

Hallo herbivore,

die Begriffe Instanz und Objekt sind Synonyme und können an (fast) allen Stellen im Text ausgetauscht werden, ohne dass dadurch die Bedeutung geändert wird.

wo eigentlich nicht?

Hinrich

Hallo hinrich,

Du hast ein Objekt vom Typ ClassA, welches aber ohne das Werfen einer Exception auf ClassB gecastet werden kann.

nein, das stimmt nicht. Es wird ein Objekt vom Typ ClassB erzeugt. Deshalb heißt es ja auch **new** Class**B**. Wie schon oben gesagt, ist die folgende Zuweisung ein zweiter Schritt, der keinen Einfluss auf die Erzeugung selbst hat. Ein Objekt bekommt durch seine Erzeugung den hinter new angegeben Typ, der während der gesamten Lebensdauer des Objekts unverändert bleibt.

welches aber ohne das Werfen einer Exception auf ClassB gecastet werden kann.

Das Objekt ist ja schon vom Typ ClassB. Der Typ des Objekts muss also nicht geändert werden und kann auch gar nicht geändert werden. Siehe [gelöst] Generische Methode, auf eigene Instanz zugreifen.

wo eigentlich nicht?

Streng genommen ist "Instanz" der deutschen Wortbedeutung nach überhaupt kein Synonym zu Objekt ist, obwohl es fast alle Informatiker und Programmierer (und deshalb auch ich) so benutzen. Die korrekte Übersetzung von "instance" wäre "Exemplar". Siehe Exemplarische Instanzen. Wenn man das weiß, kann man sich die Sache vielleicht besser anhand der altbekannten Begriffe "Zeitschrift" und "Exemplar" überlegen. In einem Kontext, in dem es um Zeitschriften geht, kann man "Zeitschrift" fast überall durch "Exemplar" ersetzen. Es gibt aber auch eine winzige Nuance in der Bedeutung. Von "Exemplar" spricht man vor allem, wenn es um ein bestimmtes Exemplar oder den Unterschied oder den Zusammenhang zwischen mehreren Exemplaren geht, wogegen "Zeitschrift" gerne allgemeiner für jede beliebige Zeitschrift oder sogar als Oberbegriff für alle Exemplare verwendet wird. Genauso verhält sich das bei "Objekt" und "Instanz".

herbivore