Lösungsvorschläge
Transcription
Lösungsvorschläge
TECHNISCHE UNIVERSITÄT MÜNCHEN FAKULTÄT FÜR INFORMATIK Praktikum Grundlagen der Programmierung Lösungsvorschläge zu Blatt 7 Robert Eigner, Florian Forster Praktikum Grundlagen der Programmierung Aufgabe 34 Mehrfachvererbung (Lösungsvorschlag) a) Vererbungsmodell: b) Die abstrakte Oberklasse für alle Superhelden: public abstract class Superheld { abstract public void kaempfen (); } Die Schnittstelle für fliegende Superhelden: public interface KannFliegen { public void fliegen (); } Die Schnittstelle für denkende Superhelden: public interface KannDenken { public void denken (); } SS 2010 14.06.2010 Lösung 7/ Seite 2 Die Schnittstelle für Karate-Superhelden: public interface KannKarate { public void karate (); } Einzelne Vertreter der Superhelden-Gattungen: public class Conan extends Superheld { public void kaempfen () { System . out . println (" Conan kämpft " ); } } public class Superman extends Superheld implements KannFliegen { public void kaempfen () { System . out . println (" Superman kämpft " ); } public void fliegen () { System . out . println (" Superman fliegt " ); } } public class Spiderman extends Superheld implements KannFliegen , KannDenken { public void kaempfen () { System . out . println (" Spiderman kämpft " ); } public void fliegen () { System . out . println (" Spiderman fliegt " ); } public void denken () { System . out . println (" Spiderman denkt " ); } } public class ChuckNorris extends Superheld implements KannKarate { public void kaempfen () { System . out . println (" Chuck Norris kämpft " ); } public void karate () { System . out . println (" Chuck Norris kann Karate " ); } } Lösung 7/ Seite 3 Aufgabe 35 verkettete Listen (Lösungsvorschlag) public class IntNode { private int value ; private IntNode next ; public IntNode (int i) { value = i; } public int getValue () { return value ; } public void setValue (int i) { value = i; } public IntNode getNext () { return next ; } public void setNext ( IntNode n) { next = n; } } public class LinkedIntList { private IntNode first ; public LinkedIntList () { first = null; } public boolean isEmpty () { return first == null; } public void insert (int i) { if ( first == null) { first = new IntNode (i ); } else { IntNode current = first ; while( current . getNext () != null) { current = current . getNext (); } current . setNext (new IntNode (i )); } } Lösung 7/ Seite 4 public void remove (int i) { IntNode current = first ; IntNode predecessor = first ; while( current != null) { if ( current . getValue () == i) { if ( current . getNext () != null) { current . setValue ( current . getNext (). getValue ()); current . setNext ( current . getNext (). getNext ()); } else { if ( current == first ) { first = current = predecessor = null; } else { predecessor . setNext (null); } } return; } predecessor = current ; current = current . getNext (); } } @Override public String toString () { StringBuffer sb = new StringBuffer (); IntNode current = first ; while ( current != null){ sb . append ( current . getValue ()). append ( ’ ’); current = current . getNext (); } return sb . toString (); } } Alternative Lösung, die nicht jedesmal die komplette Liste bis ans Ende durchlaufen muss, wenn am Ende ein Element eingefügt werden soll. Dies wird erreicht, indem ein zweiter Zeiger mitgeführt wird, der auf das Ende der Liste zeigt: public class LinkedIntList { private IntNode head , last ; public boolean isEmpty () { return head == null; } public void insert (int i) { if ( isEmpty ()) { head = new IntNode (i ); last = head ; } else { last . setNext (new IntNode (i )); last = last . getNext (); Lösung 7/ Seite 5 } } public void remove (int i) { if (! isEmpty ()) { if ( head . getValue () == i) { if ( last == head )// remove the last element (in this case // the head) of the list => update last // reference last = null; head = head . getNext (); } else { IntNode current = head ; while ( current . getNext () != null && current . getNext (). getValue () != i) current = current . getNext (); if ( current == last )// not found => return return; if ( last == current . getNext ())// remove the last element // of the list => update // last reference last = current ; current . setNext ( current . getNext (). getNext ()); } } } @Override public String toString () { StringBuffer sb = new StringBuffer (); IntNode current = head ; while ( current != null) { sb . append ( current . getValue ()). append (" " ); current = current . getNext (); } return sb . toString (); } } Lösung 7/ Seite 6 Aufgabe 36 Overriding & Overloading (Lösungsvorschlag) Ja, das Programm kompiliert und erzeugt folgende Ausgabe: Konstruktor Konstruktor Konstruktor A. test () B. test () ---------Konstruktor Konstruktor B. test () ---------Konstruktor Konstruktor Konstruktor C. test () A. test () ---------Konstruktor Konstruktor Konstruktor C. test () B. test () ---------A. test () D. test (A a) B. test () D. test (A a) B. test () D. test (B b) A A B A B A B C(A a) A B C(A a) Overriding (Überschreiben): eine Methode einer Subklasse hat den gleichen Namen, dieselbe Paramterliste und denselben Rückgabewert wie eine Methode seiner Elternklasse: die Subklasse überschreibt eine Methode seiner Elternklasse. Eine überschreibende Methode kann auch einen Untertyp des Typs zurückgeben, der von der überschriebenen Methode zurückgegeben wird (kovarianter Rückgabetyp). Der Zugriffsmodifizierer der überschreibenden Methode darf dabei nicht einschränkender sein als der der überschriebenen Methode, d. h. eine Methode die public deklariert ist kann nicht mit einer als protected deklarierten Methode überschrieben werden. Zur Fehlervermeidung sollte die b̈erschreibende Methode in der Subklasse mit der @OverrideAnnotation (verfügbar seit Java 1.5) gekennzeichnet werden. Bei deren Verwendung wird vom Compiler dann überprüft, ob die entsprechend gekennzeichnete Methode tatsächlich eine Methode einer Elternklasse überschreibt. Die Typüberprüfung wird schon vom Compiler durchgeführt. Overloading (Überladen): innerhalb einer Klasse sind mehrere Methoden mit gleichem Namen aber unterschiedlicher Parameterliste vorhanden (Anzahl und/oder Typ der Parameter sind verschieden): die Methoden sind „überladen“. Der Rückgabetyp ist dabei irrelevant, d. h. eine Klasse kann nicht über zwei Methoden mit demselben Namen und derselben Parameterliste verfügen, die sich nur im Rückgabetyp unterscheiden. Die überladenen Methoden müssen dabei nicht zwingend in derselben Klasse definiert sein. So kann eine Methode einer Subklasse eine von der Elternklasse geerbte Methode überladen. Die Typüberprüfung wird erst zur Laufzeit durchgeführt. Somit wird auch erst zur Laufzeit festgestellt, welche Methode aufzurufen ist.