Polymorphie Aufgaben

programm2008

programm2008

Ambitioniertes Mitglied
0
Hallo Leute,

ich versuche zurzeit diese Aufgabe zu lösen (Siehe Anhang) allerdings komme ich an einer Stelle nicht weiter



Also erstmal erklär ich wie ich das mache. Nehmen wir dazu die dritte Aufgabe:


Code:
ff.gg(ff);

Ich geh da so vor, dass ich mir erstmal ff angucke. Da wurde ein Mitte in ein Oben abgespeichert. Ok das heisst für mich guck in die Mitte methode rein wo die Methode auch ausgeführt werden soll.

dann methoden name gg ist ja identisch dass brauch ich net beachten.

als letztes den Parameter angucken (ff) dabei beachte ich nun nicht die rechte Seite der Deklaration, sondern die Linke also Oben ist hier wichtig.

Also gehe ich zusammenfassend in Mitte rein und führe die Methode mit dem "Oben" aus. Die Ausgabe lautet also "L". So weit so gut


Beim nächsten Befehl funktioniert das allerdings nicht


Code:
ff.gg(uu);

Also gehe ich wie gerade vor ich guck mir die Deklaration von ff an aber die rechte Seite.

Ein Mitte Objekt wurde in ein Oben Objekt abgespeichert. Das Mitte ist wichtig, dort wird also die Methode ausgeführt.

Und Parameter wie gesagt die linke Seite beachten wobei hier beide Unten Objekte sind.


Zusammenfassend in der Mitte Klasse den Unten Parameter ausführen. Also "M".

Allerdings kommt da nicht M raus sondern B ich versteh das einfach nicht. Wieso geht der in die Klasse Oben und führt dort den Mitte Parameter aus???
 
Edit: macht für mich auch kein Sinn! Wenn er bei ff.gg (ff) L ausgibt warum dann nicht M bei dem 4.!!!

Für mich kommt da ABLMXM raus
wie ist denn deine richtige Lösung?
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: programm2008
Hey erstmal danke fürs Antworten

Allerdings ist dies die richtige Ausgabe

A B L B X M
 
Quelle und Begründung? :)



Versteh ich aber auch nicht...ff ruft doch die Mitte funktion auf und übergibt ein uu

Der ursprüngliche Beitrag von 07:13 Uhr wurde um 07:25 Uhr ergänzt:

Eigentlich müsste er die Mitte Funktion ansprechen warum benutzt er die verrate gg (mitte) anstatt gg (unten) die viel besser passt imho
 
Der Trick ist, dass der Typ der Variable ff Oben ist und nicht Mitte. In Oben gibt es nur die Signaturen gg(Oben) und gg(Mitte), wobei die Aufruf dann an letzere gebunden wird.
 
da ist trotzdem was faul...der aufruf davor liefert auch die methode aus der Mitte Klasse

Zur Compilezeit ist ff ein Oben das stimmt schon aber zur runtime wird es zu einem Mitte objekt.

Das heißt in Code:

PHP:
class A
{
    public void method()
    {
        log.d(Tag,"A");
    }
}

class B extends A
{
    public void method()
    {
        log.d(Tag,"B");
    }
}
...
A a=new B();
...
a.method();        //1
((A)a).method(); //2

1 gibt B aus
2 gibt A aus

a ruft die Methoden aus B auf...deswegen wundere ich mich...ich werds mal selbst testen wenn ich wieder at home bin


lg

jaiel
 
Jaiel schrieb:
da ist trotzdem was faul...der aufruf davor liefert auch die methode aus der Mitte Klasse

Zur Compilezeit ist ff ein Oben das stimmt schon aber zur runtime wird es zu einem Mitte objekt.

Wir haben hier zwei Sorten Polymorphismus:
1.) Die Signaturauswahl, die in Java immer statisch und ist, und
2.) Late Bindung, die zur Laufzeit bestimmt, welche Implementierung einer Signatur zum tragen kommt.

A und L (und X) haben die selbe Signatur gg(Oben). Wird gg in einem Objekt vom Typ Mitte aufgerufen, holt das Late Bindung die Methode L aus Mitte.

B und Z haben die Signatur gg(Mitte). Auch zwischen ihnen wird im Late Bindung entschieden.

M steht mit seiner Signatur gg(Unten) allein auf weitem Feld.

1 gibt B aus
2 gibt A aus
Glaub ich nicht :D
 
Zuletzt bearbeitet:
Jo stimmt es gibt
B
B
aus

Der ursprüngliche Beitrag von 13:47 Uhr wurde um 13:50 Uhr ergänzt:

Hab Grad getestet omg warum gibt er B aus (vom Beispiel des Threadersteller)
Unmöglich hier:(

Der ursprüngliche Beitrag von 13:50 Uhr wurde um 13:52 Uhr ergänzt:

Also meine Lösung war ABLMXM aber es ist doch ABLBXM

Der ursprüngliche Beitrag von 13:52 Uhr wurde um 13:55 Uhr ergänzt:

Und was meinst du genau mit auf weitem Feld stehen durch die späte Bindung sollte ja eigentlich meiner Meinung nach die gg (Unten u) genommen werden...Warum nimmt er die gg (Mitte)
 
Zu M gibt es keine Methode, die sie durch Late Bindung überläd oder durch die sie überladen wird.

gg(Unten) kann niemals gg(Mitte) überladen. (Zumindest nicht in Java :D)

Stell dir das einfach so vor, dass die statischen(!) Typnamen der Parameter in Wahrheit Teil des Methodennamens sind.
Beim Kompilieren muss der Compiler bei Aufrufen den Namen dann dazuraten, ohne eine Datenflussanalyse zu betreiben.

Deshalb nannte man den Signaturpolymorphismus auch bisweilen "Naming Polymorphism".
 
Zuletzt bearbeitet:
Ok ich verstehe nach wie vor nicht wie ich jetzt auf die Ausgaben zu kommen habe :confused2:

Der ursprüngliche Beitrag von 17:12 Uhr wurde um 17:21 Uhr ergänzt:

Wenn ich mir z.B den allerletzten Methodenaufruf angucke : uu.gg(uu);

Da wird ein Unten Objekt erstellt und ein Unten Parameter übergeben. Es wird aber nicht die nächste Kompatible Methode (Mitte m) genommen sondern der geht in die Mitte Klasse und dann da in die (Unten u) methode. Ok jetzt kann man sagen, dass ist noch näher an dem Unten deswegen wird das ausgewählt. Aber wie weiß ich jetzt wo wann was ausgewählt wird.

Beim beispiel ff.gg(uu);

achten wir auf die linke Seite d.h. die Methode in OBEN wird ausgeführt

Oben ff = new Mitte();

Beim beispiel ff.gg(ff); allerdings

Oben ff = new Mitte();

wird die Methode in MITTE ausgeführt. Ich versteh nicht wann was ausgeführt wird.
 
Nochmal gaaaanz langsam.

Es gibt hier drei Methoden:

x.gg(Oben) // implementiert als A L X
x.gg(Mitte) // implementiert als B Z
x.gg(Unten) // implementiert als M

Während des Kompilierens wird entscheiden, welche der drei Methoden gemeint ist, wobei nur der Typ der Variable benutzt wird und nicht der aktuelle Wert (der ergibt sich ja normalerweise erst zur Laufzeit).

Bim letzten Aufruf, hast du die Signatur Unten.gg(Unten). Da Unten gg(Oben) gg(Mitte) und gg(Unten) hat, passt die Signatur gg(Unten) am besten. (Auch wenn es in Mitte definiert ist.)

ff.gg(ff) hat die Aufrufsignatur Oben.gg(Oben) (was an ff zugewiesen wird, ist zur Compilezeit irrelevant) gehört also zur ALX Gruppe, beim Lauf des Programms sind haben wir eine Mitte Objekt, es gibt aus der Gruppe deshalb L.
 
  • Danke
Reaktionen: programm2008
Ich hab ein knoten im Kopf keine Ahnung
was passiert hier:
(B erbt A und haben folgende methode: method (int x){log.d (tag,"A"/"B"}; )


A a = new B ();

a.method (1);

Was wird ausgegeben A oder B?
Wenn du jetzt sagst B dann Fang ich an zu weinen
 
DieGoldeneMitte schrieb:
Nochmal gaaaanz langsam.

Es gibt hier drei Methoden:

x.gg(Oben) // implementiert als A L X
x.gg(Mitte) // implementiert als B Z
x.gg(Unten) // implementiert als M

Während des Kompilierens wird entscheiden, welche der drei Methoden gemeint ist, wobei nur der Typ der Variable benutzt wird und nicht der aktuelle Wert (der ergibt sich ja normalerweise erst zur Laufzeit).

Bim letzten Aufruf, hast du die Signatur Unten.gg(Unten). Da Unten gg(Oben) gg(Mitte) und gg(Unten) hat, passt die Signatur gg(Unten) am besten. (Auch wenn es in Mitte definiert ist.)

ff.gg(ff) hat die Aufrufsignatur Oben.gg(Oben) (was an ff zugewiesen wird, ist zur Compilezeit irrelevant) gehört also zur ALX Gruppe, beim Lauf des Programms sind haben wir eine Mitte Objekt, es gibt aus der Gruppe deshalb L.


Hab hier mal ein Bespiel bei dem ich die Anleitung beachtet habe allerdings kommt wieder was falsches raus :sad:

Erstmal Kategorisieren:

Object Y, L
Top C
Middle D,M
Bottom Z,E

Dann den Parameter angucken: Top

Weil ein Middle im Top steckt wird eine Methode zwischen diesen zwei Klassen gewählt.

--> Ausgabe müsste C sein, Ist es aber nicht sondern Y

Die Top Methode ist doch viel zutreffender als das Object in der Top Klasse. Ich versteh das einfach nicht


 
Jaiel schrieb:
Was wird ausgegeben A oder B?
Wenn du jetzt sagst B dann Fang ich an zu weinen

Tja, dann muss ich dir ein Taschentuch reichen.
Du implementierst Signatur-Polymorphisch eine Methode method(int). Da greift ganz normal Late Binding.

@programm2008 Du hast dir doch schon überlegt, welche Signaturen es gibt.

Denk dir nach dem letzten Konstruktor einfach ein paar Programmierbefehle hin. tt = x(); tm=y(); tb=z(); Mit anderen Worten niemand weiss zur Compilzezeit, welchen Typ das Objekt bei den f Aufrufen hat, du hast nur den Typ der Variable. Damit musst du (bzw. der Compiler) die richtige Signatur bestimmen. Wenn du das gemacht hast, kannst du dir die extra Befehle wieder wegdenken und ueberlegen, welche Implementierung der Signatur durch Late Bindung zum Zuge kommt.

Und bevor ich hier komplette Übungszettel löse, werde ich mich ab jetzt in Schweigen hüllen :D
 
Zuletzt bearbeitet:
:sad::sad::sad:
 
Die Erklärung für die Ausgabe L ist eigentlich recht einfach:

Oben ist der Referenztyp von ff.
ff ist ein Objekt vom Typ Mitte.

Oben erlaubt folgende Methoden: gg(Oben o) und gg(Mitte m).

Ausgeführt werden aber die Methoden des Objekts

Im Fall ff.gg(ff) wird die Methode gg des Objekt vom Typ Mitte aufgerufen: m.gg(O). Also wird L ausgegeben.

Im Speicher wird ein Objekt vom Mitte abgelegt. Dem Objekt wird danach eine Referenz vom Typ Oben zugewiesen.

Der Haken ist hier, dass der Interpreter immer den Typ über die Referenz bestimmt.

Das gilt aber nur für typensichere Sprachen!! ;)
 
Zuletzt bearbeitet:
OK aber ich verstehe nicht wieso bei ff.gg (ff) die Methode aus Mitte aufruft mit dem Oben Parameter aber bei ff.gg (uu) schaut er in Mitte rein sieht dass die Methoden super.gg (Oben), gg (Oben), gg (Mitte) und gg(Unten) vorhanden sind.
anstatt gg (Unten) zu nehmen da uu ein Unten ist nimmt er gg (Mitte) ... oder schaut er gar nicht in Mitte rein sondern sieht nur die Oben Methoden wobei dass kein Sinn macht da vorher L ausgegeben wurde und er in Mitte nach den richtigen Methoden sucht oh mann
ich weiß dass ich falsch denke aber ich hab ein knoten einfach
 
DieGoldeneMitte hat das doch schon ganz gut erklärt. Die Auswahl der Methodensignatur (also inklusive Typen der Parameter) erfolgt statisch mit den sicheren Typinformationen, also den Typen wie sie im Code definiert sind. Die Auswahl der Methode mit dieser FESTGELEGTEN Signatur erfolg zur Laufzeit am Typ den das Objekt zur dieser Zeit tatsächlich hat.
Auswahl der Methodensignatur -> Compilezeit
Auswahl der Methode mit dieser Signatur -> Laufzeit
 
  • Danke
Reaktionen: DieGoldeneMitte
Wenigstens einer versteht mich hier :wubwub:
 
Naja polymorphie scheint öfters für Probleme zu sorgen :D
Zumindest scheinen Studenten in den Klausuren öfters daneben zu liegen :huh:
 

Ähnliche Themen

lordzwieback
Antworten
22
Aufrufe
1.830
lordzwieback
lordzwieback
H
Antworten
0
Aufrufe
581
Hungrig
H
H
Antworten
2
Aufrufe
2.043
swordi
S
Zurück
Oben Unten