Benutzer-Werkzeuge

Webseiten-Werkzeuge


klassen2:casting:start

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.


klassen2:casting:start [2024/08/31 12:03] (aktuell) – angelegt - Externe Bearbeitung 127.0.0.1
Zeile 1: Zeile 1:
 +====== Type Casting und der Operator instanceof ======
 +
 +{{ youtube>iUYAXaDJpAA?large }}
 +
 + \\ 
 +Da Variablen vom Datentyp einer Oberklasse auch auf Objekte der Unterklasse zeigen können, ergeben sich Situationen, in denen erst zur Laufzeit bekannt ist, welchen Datentyp das Objekt hat, auf das eine bestimmte Variable zeigt. Wie man damit umgeht, zeige ich konkret an einem Beispiel:
 +
 +=== Die Klasse Tier ===
 +Wir beginnen mit einer einfachen Klasse, die ein Tier beschreibt. Jedes Tier hat ein Attribut ''Name'', dessen Wert an den Konstruktor übergeben wird. Die Methode ''schreibeName()'' schreibt ihn auf den Bildschirm:
 +<HTML>
 +
 +<div class="java-online" style="height: 370px; width: 100%" data-java-online="{'withBottomPanel': false, 'id': 'Casting1'}">
 +
 +<script type="text/plain" title="Tier.java">
 +Tier t = new Tier("Nemo");
 +t.schreibeName();
 +class Tier {
 +
 +   protected String name;
 +
 +   public Tier(String name) {
 +      this.name = name;
 +   }
 +
 +   public void schreibeName() {
 +      println("Name: " + name);
 +   }
 +}</script>
 +
 +</div>
 +
 +</HTML>
 + \\ 
 +=== Die Klassen Hund und Katze ===
 +Nun gibt es Tiere, die nicht nur einen Namen besitzen, sondern auch noch Methoden haben, die andere Tiere nicht haben, bspw. Hunde, die bellen können und Katzen, die miauen können. Wir modellieren sie als Unterklassen der Klasse Tier, instanzieren ein Hund-Objekt und ein Katzen-Objekt und rufen deren Methoden auf:
 + \\ 
 +<HTML>
 +
 +<div class="java-online" style="height: 450px; width: 100%" data-java-online="{ 'id': 'Casting2' , 'withBottomPanel': true}">
 +<script type="text/plain" title="Main.java">
 +Hund h = new Hund("Bello");
 +Katze k = new Katze("Snoopy");
 +
 +h.belle();
 +h.schreibeName();
 +
 +k.miaue();
 +k.schreibeName();
 +
 +Tier t = h;
 +t.schreibeName();
 +// t.belle(); // geht nicht, da die Variable t vom Typ Tier ist (obwohl sie auf ein Hund-Objekt zeigt!)
 +
 +t = k;
 +t.schreibeName();
 +</script>
 +
 +<script type="text/plain" title="Tier.java">
 +class Tier {
 +
 +   protected String name;
 +
 +   public Tier(String name) {
 +      this.name = name;
 +   }
 +
 +   public void schreibeName() {
 +      println("Name: " + name);
 +   }
 +}</script>
 +
 +<script type="text/plain" title="Hund.java">
 +class Hund extends Tier {
 +
 +   public Hund(String name) {
 +      super(name);
 +   }
 +
 +   public void belle() {
 +      println("Wau Wau", Color.red);
 +   }
 +}</script>
 +
 +<script type="text/plain" title="Katze.java">
 +class Katze extends Tier {
 +
 +   public Katze(String name) {
 +      super(name);
 +   }
 +
 +   public void miaue() {
 +      println("Miau!", Color.green);
 +   }
 +   
 +}
 +</script>
 +
 +
 +</div>
 +
 +</HTML>
 +
 +==== 1.Aspekt: Zuweisung des Objekts einer Unterklasse====
 +Einer Variable vom Datentyp Tier (Oberklasse) kann man nicht nur Objekte vom Datentyp Tier zuweisen, sondern auch Objekte beliebiger Unterklassen der Klasse Tier. Im Beipsiel unten:
 +<code learnj>
 +Hund h = new Hund("Bello");
 +Tier t = h;
 +</code>
 +Nach Ausführung der Zeile 2 zeigen sowohl ''h'' als auch ''t'' auf dasselbe Hund-Objekt im Speicher. \\ 
 +Der Compiler geht davon aus, dass ''t'' auf Objekte vom Datentyp Tier zeigt und gestattet es, mit der Variablen ''t'' auf Attribute der Klasse ''Tier'' zuzugreifen und Methoden der Klasse ''Tier'' aufzurufen. Das geht auch dann gut, wenn ''t'' nicht auf ein ''Tier''-Objekt sondern - wie in diesem Fall - auf ein ''Hund''-Objekt zeigt, denn die Klasse ''Hund'' besitzt als Unterklasse der Klasse ''Tier'' ja alle ihrer Attribute und Methoden. Zulässig ist also beispielsweise ''t.schreibeName()''. \\ 
 +Nicht zulässig ist ''t.belle()'' in Zeile 6, **obwohl t zum Zeitpunkt des Aufrufs auf ein Hund-Objekt zeigt!** \\
 +
 +Auch die Zuweisung ''t = k;'' ist zulässig, denn auch das Objekt ''k'' (vom Typ ''Katze'') ist von einer Unterklasse der Klasse ''Tier''. Nicht möglich ist wiederum ''t.miaue()'' in Zeile 10, **obwohl t zum Zeitpunkt des Aufrufs auf ein Katze-Objekt zeigt.** \\ 
 +
 +<HTML>
 +
 +<div class="java-online" style="height: 300px; width: 100%" data-java-online="{ 'id': 'Casting3', 'withBottomPanel': true }">
 +<script type="text/plain" title="Main.java">
 +Hund h = new Hund("Bello");
 +Katze k = new Katze("Snoopy");
 +
 +Tier t = h;
 +t.schreibeName();
 +// t.belle(); // geht nicht, da die Variable t vom Typ Tier ist (obwohl sie gerade auf ein Hund-Objekt zeigt!)
 +
 +t = k;
 +t.schreibeName();
 +// t.miaue(); // geht nicht, da die Variable t vom Typ Tier ist (obwohl sie gerade auf ein Katze-Objekt zeigt!)
 +
 +</script>
 +
 +<script type="text/plain" title="Tier.java">
 +Tier t = new Tier("Nemo");
 +t.schreibeName();
 +
 +class Tier {
 +
 +   protected String name;
 +
 +   public Tier(String name) {
 +      this.name = name;
 +   }
 +
 +   public void schreibeName() {
 +      println("Name: " + name);
 +   }
 +}</script>
 +
 +<script type="text/plain" title="Hund.java">
 +class Hund extends Tier {
 +
 +   public Hund(String name) {
 +      super(name);
 +   }
 +
 +   public void belle() {
 +      println("Wau Wau", Color.red);
 +   }
 +}</script>
 +
 +<script type="text/plain" title="Katze.java">
 +class Katze extends Tier {
 +
 +   public Katze(String name) {
 +      super(name);
 +   }
 +
 +   public void miaue() {
 +      println("Miau!", Color.green);
 +   }
 +   
 +}
 +</script>
 +
 +
 +</div>
 +
 +</HTML>
 +
 +== Aufgaben: ==
 +  - Entferne das Kommentarzeichen %%//%% am Beginn der Zeile 6 bzw. 10. Welche Fehlermeldung zeigt der Compiler an? Warum tut er das?
 +  - Nach Zeile 10 wird folgendes Programm ergänzt:
 +<code learnj>
 +   Katze k1 = h;
 +   h.schreibeName();
 +</code>
 +sind diese Anweisungen zulässig? Falls "nein": Warum nicht? Probiere sie aus, indem Du sie ins Beispiel oben einfügst! \\ \\ 
 +[[.aufgabe12:loesungen:start|Lösungen]]
 +==== 2. Aspekt: Casten ====
 +Wurmt es Dich nicht auch, dass im Falle von 
 +<code learnj>
 +Hund h = new Hund("Bello");
 +Tier t = h;
 +t.belle();
 +</code>
 +die Anweisung in Zeile 3 nicht möglich ist, obwohl wir sicher wissen, dass ''t'' gerade auf ein ''Hund''-Objekt zeigt? Warum "weiß" das der Compiler nicht? \\ 
 +Denke Dir folgende Variante:
 +<code learnj>
 +Hund h = new Hund("Bello");
 +Katze k = new Katze("Snoopy");
 +Tier t;
 +if(Math.random() < 0.5){
 +  t = h;
 +} else {
 +  t = k;
 +}
 +t.belle();
 +</code>
 +Zur Compilezeit (also während der Compiler das Programm übersetzt und auf Korrektheit überprüft) kann der Compiler nicht wissen, ob sich bei der Ausführung des Programms in ''t'' ein ''Hund''-Objekt oder ein ''Katze''-Objekt befindet. Er kann nur sicher davon ausgehen, dass es ein Objekt ist, dass die Attribute und Methoden der Klasse ''Tier'' besitzt. \\ 
 +Falls wir als Programmierer uns sicher sind, dass in der Variable ''t'' ein Hund-Objekt ist, können wir das dem Compiler aber "sagen", indem wir der Variable in Klammern die Klasse des Objekts voranstellen, auf das die Variable zeigt. Diesen Vorgang nennt man **casten**:
 +
 +<HTML>
 +
 +<div class="java-online" style="height: 300px; width: 100%" data-java-online="{ 'id': 'Casting4', 'withBottomPanel': true}">
 +<script type="text/plain" title="Main.java">
 +Hund h = new Hund("Bello");
 +
 +Tier t = h;
 +t.schreibeName();
 +((Hund)t).belle(); 
 +
 +// Variante mit zusätzlicher Variable:
 +Hund h2 = (Hund)t;
 +h2.belle();
 +
 +</script>
 +
 +<script type="text/plain" title="Tier.java">
 +class Tier {
 +
 +   protected String name;
 +
 +   public Tier(String name) {
 +      this.name = name;
 +   }
 +
 +   public void schreibeName() {
 +      println("Name: " + name);
 +   }
 +}</script>
 +
 +<script type="text/plain" title="Hund.java">
 +class Hund extends Tier {
 +
 +   public Hund(String name) {
 +      super(name);
 +   }
 +
 +   public void belle() {
 +      println("Wau Wau", Color.red);
 +   }
 +}</script>
 +
 +<script type="text/plain" title="Katze.java">
 +class Katze extends Tier {
 +
 +   public Katze(String name) {
 +      super(name);
 +   }
 +
 +   public void miaue() {
 +      println("Miau!", Color.green);
 +   }
 +   
 +}
 +</script>
 +
 +
 +</div>
 +
 +</HTML>
 +
 +== Aufgaben ==
 +3. Nimm in Zeile 8 das Casting weg, schreibe also ''Hund h2 = t;''. Was passiert? Warum? \\ \\ 
 +4. Wenn wir ungerechtfertigt casten, vertraut uns der Compiler dann? Probiere es aus, indem Du die Zeile 5 ersetzt durch ''((Katze)t).miaue();''. Was passiert? Warum? \\ \\ 
 +5. Verändert das Casten durch den Term ''(Katze)t'' das Objekt, auf das ''t'' zeigt von einem ''Tier''-Objekt zu einem ''Katze''-Objekt? Begründe Deine Antwort! \\ \\ 
 + \\ 
 +[[.aufgabe345:loesungen:start|Lösungen]]
 +==== 3. Aspekt: instanceof ====
 +Oft kann eine Variable an einer Stelle des Programms zu verschiedenen Zeiten verschiedene Objekte enthalten, so dass wir im Programm flexibel darauf reagieren müssen. Für diesen Zweck gibt es den Operator ''instanceof''. Damit lässt sich testen, ob ein Objekt einer bestimmten Klasse angehört.
 +<HTML>
 +
 +<div class="java-online" style="height: 300px; width: 100%" data-java-online="{ 'id': 'Casting5', 'withBottomPanel': true}">
 +<script type="text/plain" title="Main.java">
 +Hund h = new Hund("Bello");
 +Katze k = new Katze("Snoopy");
 +
 +Tier t;
 +if(Math.random() < 0.5){
 +  t = h;
 +} else {
 +  t = k;
 +}
 +
 +if(t instanceof Hund){
 +   ((Hund)t).belle();
 +} else {
 +   ((Katze)t).miaue();
 +}
 +
 +</script>
 +
 +<script type="text/plain" title="Tier.java">
 +class Tier {
 +
 +   protected String name;
 +
 +   public Tier(String name) {
 +      this.name = name;
 +   }
 +
 +   public void schreibeName() {
 +      println("Name: " + name);
 +   }
 +}</script>
 +
 +<script type="text/plain" title="Hund.java">
 +class Hund extends Tier {
 +
 +   public Hund(String name) {
 +      super(name);
 +   }
 +
 +   public void belle() {
 +      println("Wau Wau", Color.red);
 +   }
 +}</script>
 +
 +<script type="text/plain" title="Katze.java">
 +class Katze extends Tier {
 +
 +   public Katze(String name) {
 +      super(name);
 +   }
 +
 +   public void miaue() {
 +      println("Miau!", Color.green);
 +   }
 +   
 +}
 +</script>
 +
 +
 +</div>
 +
 +</HTML>
 +
 +
 +
  
klassen2/casting/start.txt · Zuletzt geändert: 2024/08/31 12:03 von 127.0.0.1