sicheres/unsicheres Casten bei Objekten

MOEP_BIBER

Aktives Mitglied
Hey Leute,

hab ne Frage zum Casten von Objekten hier erstmal der Code:

Java:
class Superklasse {
    public final int variable;
    public Superklasse(int variable) {
        this.variable = variable;
    }
}

Java:
class Subklasse extends Superklasse {
    public int variable;
    public Subklasse(int variable) {
        super(5 * variable);
        this.variable = variable;
    }
}

Java:
public class SuperSubApp
{
    public static void main(String[] args)
    {
        Subklasse sub1 = new Subklasse(4);
        Superklasse super2 = sub1;

        System.out.println("sub1.variable " + sub1.variable);
        System.out.println("super2.variable " + super2.variable);
    }
}

So nun zu meiner Frage:

Wieso ist die super2.variable 20? Wird da nur der super-Konstruktor in der Subklasse beim Cast aufgerufen?
Ich hab beim Lesen des Codes gedacht super2.variable ist genau so 4 wie sub1.variable.
Hab allgemein recht wenig zum sicheren bzw unsicheren Casten gefunden wäre nett wenn jemand ne gute Informationsquelle hätte.

MfG Biber
 
Zuletzt bearbeitet:
First, you must understand, that by casting you are not actually changing the object itself, you are just labeling it differently.
For example, if you create a Cat and upcast it to Animal, then the object doesn't stop from being a Cat. It's still a Cat, but it's just treated as any other Animal and it's Cat properties are hidden until it's downcasted to a Cat again.

Quelle: Upcasting, downcasting

Aber das ist auch nur bedingt hier passend. Du castest ja nix... Du "labelst" in Zeile 6 nur eine Cat als Animal. Die Attribute sind nach wie vor die von Cat
 
Hab mir die seite durchgelesn und eure Posts, aber kapiers noch immer nich ???:L

Könnte mir jemand Schritt für Schritt erklären was passiert?
Debugger bringt mich auch nicht weiter-.-

Steh grad echt aufm schlauch.
 
Du solltest in der SubKlasse die Zeile
Code:
public int variable;
löschen und in der SuperKlasse das
Code:
final
vor der Variable entfernen. Dann wird auch wirklich in beiden Fällen die gleiche Variable benutzt. In deinem Beispiel sind es zwei unterschiedliche Variablen namens
Code:
variable
.

Edit: Das ist übrigens auch das, was André Uhres wohl meinte. 🙂
 
Object obj = new String("HALLO WELT");

Object ist dein Label. D.h. du hast jetzt ein Stringobjekt, das sich allerdings hinter Object versteckt und somit stehen dir auch nur die Methoden von Object zur Verfügung. Erst mit einem Downcast kannst du die Variable obj anders Labeln und die Attribute und Methoden von String in den Vordergrund holen.

Java:
    	Object obj = new String("HALLO WELT");
    	System.out.println(obj.length()); //Funktioniert nicht! Die length-Methode von String ist verdeckt!!
    	System.out.println(((String)obj).length()); //Funktioniert
    	String s = (String)obj;
    	System.out.println(s.length()); //Funktioniert

Auf dem Link von oben ist das wirklich sehr gut beschrieben.

noch erweiternd: Du erzeugst einmal eine Katze und "deklarierst" diese mit einer einfachen zuweißen als Tier (hier erfolgt ein impliziter upcast). Dadurch bleibt es aber nach wie vor eine Katze und somit ändern sich auch die Attribute nicht. Nochmal zum Quote am Anfang:
First, you must understand, that by casting you are not actually changing the object itself, you are just labeling it differently.

rückwirkend betrachtet bin ich glaub mit meiner Erklärung etwas am Ziel vorbeigeschossen 😀. Hatte das beim ersten Überfliegen anders interpretiert 😉
 
Zuletzt bearbeitet:
@gonzo: Das ist kein von mir erstelltes Beispiel, sondern eine Aufgabe einer Altklausur. Das heißt also dass muss so sein und is kein von mir geschriebener Fehler oder so.

@nrg: Den Aspekt hab ich in dem Link verstanden nur kapier ich nicht wie mir das bei meiner Aufgabe hilft ???:L

Ich glaub langsam komm ich der Lösung aber näher:

Java:
Superklasse super2 = sub1;
daraus folgt:

Java:
public Subklasse(4) {
        super(5 * 4);
        this.variable = 4;
    }

Dadurch wird die variable in der Superklasse 20 und this.variable = 4 bewirkt nichts, da es sich ja auf die Variable in der Subklasse bezieht, welche super2 gar nicht besitzt oder?
 
@gonzo: Das ist kein von mir erstelltes Beispiel, sondern eine Aufgabe einer Altklausur. Das heißt also dass muss so sein und is kein von mir geschriebener Fehler oder so.

Ist ja auch kein Fehler ansich, nur dachte ich, dass du es anders machen wolltest und dich vertan hast. 😉

Dadurch wird die variable in der Superklasse 20 und this.variable = 4 bewirkt nichts, da es sich ja auf die Variable in der Subklasse bezieht, welche super2 gar nicht besitzt oder?

In der Klasse SuperKlasse gibt es eine Variable namens
Code:
variable
, die den Wert 20 hat. In der Klasse SubKlasse gibt es eine Variable namens
Code:
variable
, die den Wert 4 hat. Die Variable aus der SuperKlasse ist für die SubKlasse nicht sichtbar, weil sie überschrieben wird (gleicher Name). Castest du dein Objekt zum Typ SuperKlasse, siehst du jedoch lediglich die Methoden und Variablen eben dieser SuperKlasse und da ist in dem Fall die Variable mit dem Wert 20.
 
ja. siehe letzten edit oben 😉. Aber im Grunde passt das schon auch hier. Du labelst mit dem impliziten Upcast das Objekt anders. Wenn es in der Superklasse garkeine Variable variable gäbe, würde er dir das nicht mal kompilieren. Durch den Upcast werden halt einfach die Attribute von Subklasse verdeckt und die von Superklasse kommen zur Vorschein. Dort wurde aber variable anders intialisiert.

Um kurz und bündig auf den Punkt zu kommen, kann man hier eigentlich nur André Uhres zitieren. Das triffts ganz gut 😉.
 
Ok danke soweit so gut.
Jedoch wenn ich jetzt den Downcast mache zurück auf die Subklasse, so sollte doch die Variable aus der Subklasse wieder sichtbar werden oder?

also:

Java:
super2 = (Subklasse)super2;
System.out.println("super2.variable " + super2.variable);

Jedoch wird wieder 20 ausgegeben.
Wie könnte ich wenn ich wollen würde auf die variable aus der Subklasse des super2 Objekts zugreifen?
Oder anders rum: Wie könnte ich auf die variable aus der Superklasse des sub1 Objekts zugreifen?

Ps: Das ist nur ein Bruchteil einer Aufgabe die auf 12 Minuten erledigt werden sollte seh ich grad oO
 
dein Label von super2 ist doch nach wie vor Superklasse. Wenn dann schon so:

Subklasse wasAuchImmer = (Subklasse)super2;
 
Achtung: Das sind beides dieselben Objekte, lediglich die Referenzen sind von anderem Typ!

Der Aufruf
Code:
super2 = (Subklasse)super2;
ändert nichts an der Referenz, diese ist noch immer von der Superklasse.

Java:
Subklasse sub2 = (Subklasse) super2;
System.out.println("sub2.variable " + sub2.variable);
 
Die Variable super2 ist ja trotzdem noch vom Typ SuperKlasse, auch wenn du ihr ein SubKlasse-Objekt zuweist. Wichtig ist was du deklariert hast, was dann "drin ist", ist eigentlich erstmal egal, das ändert die Sichtbarkeit nicht.
 

Zurück
Oben