TECHNISCHE UNIVERSITÄT MÜNCHEN FAKULTÄT FÜR INFORMATIK Lehrstuhl für Sprachen und Beschreibungsstrukturen SS 2011 Einführung in die Informatik I Übungsblatt 10 Prof. Dr. Helmut Seidl, A. Lehmann, A. Herz, Dr. M. Petter 07.07.11 Abgabe: keine Pflichtabgabe (vor 12 Uhr) Aufgabe 10.1 (P) Vererbung Gegeben seien folgende Java-Klassen: interface I { public void f ( ) ; interface J { public void g ( ) ; class A implements I { public A( ) { System. out. p r i n t l n ( A ) ; public void f ( ) { System. out. p r i n t l n ( f ( ) in A ) ; h ( ) ; public void g ( ) { System. out. p r i n t l n ( g ( ) in A ) ; public void h ( ) { System. out. p r i n t l n ( h ( ) in A ) ; class B extends A { public B( ) { super ( ) ; public void h ( ) { System. out. p r i n t l n ( h ( ) in B ) ; public void g ( ) { System. out. p r i n t l n ( g ( ) in B ) ; super. h ( ) ; class C { public void h ( ) { System. out. p r i n t l n ( h ( ) in C ) ; class D extends B implements I, J { public void f ( ) { System. out. p r i n t l n ( f ( ) in D ) ; super. f ( ) ; g ( ) ; public void h ( ) { System. out. p r i n t l n ( h ( ) in D ) ; a) Folgende Anweisungen werden vom Compiler erfolgreich übersetzt: i) I a = new A();...................................... Richtig Falsch ii) A a = new A(); B b = a;........................... Richtig iii) B b = new D(); J j = (D) b;...................... Richtig Falsch Falsch iv) B b = new B(); I i = b;........................... Richtig Falsch v) C c = new B();...................................... Richtig Falsch vi) D d = new B();...................................... Richtig Falsch
2 b) Welche Ausgaben produzieren die folgenden Anweisungen? i) A a = new A(); a.f(); A f() in A h() in A ii) A a = (A) new B(); a.f(); A f() in A h() in B iii) B b = new B(); b.g(); A g() in B h() in A iv) C c = new C(); c.h(); h() in C v) D d = new D(); d.h(); A h() in D vi) D d = new D(); d.f(); A f() in D f() in A h() in D g() in B h() in A
3 Aufgabe 10.2 (P) Vererbung Gegeben seien folgende Java-Klassen: class L i s t { private int i n f o ; public L i s t next ; public L i s t ( int i n f o, L i s t next ) { this. i n f o=i n f o ; this. next=next ; public S t r i n g t o S t r i n g ( ) { i f ( next==null ) return i n f o+ ; ; return i n f o+, +next ; public int g e t I n f o ( ) { return i n f o ; class A { private L i s t l = f i l l L i s t ( 5 ) ; public void f ( ) { System. out. p r i n t l n ( f ( ) in A; l= +l ) ; public void g ( ) { System. out. p r i n t l n ( g ( ) in A ) ; s ( ) ; public static void s ( ) { System. out. p r i n t l n ( s ( ) in A ) ; private static L i s t f i l l L i s t ( int i ) { L i s t l = null ; for ( int j = i ; j >0; j ) l= new L i s t ( i, l ) ; return l ; public S t r i n g t o S t r i n g ( ) { S t r i n g s = ; while ( l!= null ) { s=s+ +l. g e t I n f o ( ) ; l=l. next ; return s ; class B extends A { private L i s t l ; public void f ( ) { System. out. p r i n t l n ( f ( ) in B; l= +l ) ; public void g ( ) { System. out. p r i n t l n ( g ( ) in B ) ; s ( ) ; public static void s ( ) { System. out. p r i n t l n ( s ( ) in B ) ; a) Folgende Anweisungen werden vom Java-Compiler erfolgreich übersetzt: i) List l = new List(42,l);........................ Richtig Falsch ii) List l; l = new List(42,l);..................... Richtig Falsch iii) List l = null; l = new List(42,l);............. Richtig Falsch iv) List l = null; l.next = new List(42,l);....... Richtig Falsch v) List l = new List(42,new List(13,null)); l.next.info=42;.................................... Richtig vi) List l = new List(42,null);l.next.toString();. Richtig Falsch Falsch
4 b) Welche Ausgaben produzieren die folgenden Anweisungen? i) B b = new B(); b.f(); f() in B; l=null ii) A a = new B(); a.s(); s() in A iii) A a = new B(); a.g(); g() in B s() in B iv) A a = new B(); a.f(); f() in B; l=null v) A a = new A(); a.f(); f() in A; l=5,5,5,5,5; vi) A a = new A(); System.out.println(a + + a); 5 5 5 5 5
5 Aufgabe 10.3 (P) Prismen Prismen oder Zylinder sind geometrische Körper, die durch Parallelverschiebung ihrer Grundfläche im Raum entstehen. Die folgende Abbildung zeigt als Beispiele für Prismen ein Dreiecksprisma, einen Quader und einen Zylinder, die durch Verschiebung eines Dreiecks, eines Rechtecks bzw. eines Kreises entstehen: Würfel sind durch ihre Höhe eindeutig bestimmt. Quader sind durch ihre Höhe, Länge und Breite bestimmt. Kreiszylinder sind durch ihre Höhe und den Radius ihrer Grundfläche bestimmt. Regelmässige Vielecksprismen sind durch ihre Höhe und die Seitenlänge ihrer jeweiligen Grundfläche bestimmt. In Frage kommen zum Beispiel regelmässige Dreiecksprismen oder quadratische Quader oder regelmässige n-ecksprismen. An Operationen sollen die Körper die Berechnung von Umfang und Flächeninhalt ihrer Grundfläche, die Berechnung ihrer Mantelfläche, ihrer Oberfläche und ihres Volumens zur Verfügung stellen sowie den Vergleich ihrer Volumina mit denen anderer geometrischer Körper unterstützen. In dieser Aufgabe soll eine Klassenhierarchie für diese geometrischen Körper in UML modelliert und in Java implementiert werden. a) Geben Sie ein Klassendiagramm zur Modellierung der oben genannten Körper in UML an. b) An welcher Stelle Ihrer Klassenhierarchie müssen die in a) spezifizierten Operationen implementiert werden, damit möglichst viel in Unterklassen wiederverwendet werden kann? c) Greifen Sie 3 geometrische Körper aus Ihrem Klassenmodell heraus und implementieren Sie diese in Java. Schreiben Sie zudem ein kleines Testprogramm. Hinweise: Fassen Sie gleichartige Attribute und Methoden in einer geeigneten Oberklasse zusammen. Die Fläche eines gleichseitigen Dreiecks mit Seitenlänge a ist a2 4 3 Die Fläche eines regelmässigen Sechsecks mit Seitenlänge a ist 3a2 2 3. Die Java-Klasse Math stellt in der Klassenvariablen Math.PI einen Wert für π sowie in der Klassenmethode Math.sqrt() die Berechnung der Quadratwurzel zur Verfügung. Lösungsvorschlag 10.3 a) Eine geeignete Modellierung würde folgendermaßen aussehen:
6 Prisma # hoehe: Double + mantelflaeche(): Double + oberflaeche(): Double + mvolumen(): Double + comparevolumento(prisma p): Integer RegelmaessigesPrisma # seite: Double Wuerfel Quader! laenge: Double! breite: Double Zylinder! radius: Double RegelmaessigesDreiecksPrisma QuadratischerQuader RegelmaessigesSechsecksPrisma b) Die Operationen inhaltgrundflaeche() und umfanggrundflaeche() sind von der Grundfläche des konkreten Prismas abhängig und können erst dort implementiert werden. Alle anderen Operationen können bereits in der Klasse Prisma implementiert werden und diese Implementierung an alle Unterklassen zur Wiederverwendung vererben. Dabei stützen sie sich teilweise auf die beiden Operationen inhaltgrundflaeche() und umfanggrundflaeche() ab. c) Die Oberklasse Prisma für beliebige gerade Prismen: public class Prisma { // Gemeinsames Attribut aller Prismen ist die Hoehe: protected double hoehe; public Prisma (double h) { hoehe = h; // Die Operationen umfanggrundflaeche() und inhaltgrundflaeche() // sind abhaengig von der Form des konkreten Prismas und werden // hier nur aus technischen Gruenden definiert; // In den verschiedenen Unterklassen muessen diese Methoden dann // ueberschrieben werden. Später werden sie // durch abstrakte Methoden ersetzt: public double umfanggrundflaeche(){ return 0; public double inhaltgrundflaeche(){ return 0; // Die anderen Operationen koennen bereits in dieser Klasse implementiert // werden:
7 public double mantelflaeche() { return umfanggrundflaeche() * hoehe; public double oberflaeche() { return mantelflaeche() + 2 * inhaltgrundflaeche(); public double volumen() { return inhaltgrundflaeche() * hoehe; public int comparevolumento(prisma p) { double v1 = volumen(); double v2 = p.volumen(); if (v1 < v2) return -1; else if (v1 > v2) return 1; else return 0; Die Klasse Wuerfel als Unterklasse von Prisma: public class Wuerfel extends Prisma { public Wuerfel(double h) { super(h); // Implementation der Operationen umfanggrundflaeche() und // inhaltgrundflaeche(): public double umfanggrundflaeche() { return 4 * hoehe; public double inhaltgrundflaeche() { return hoehe * hoehe; Die Klasse Quader als Unterklasse von Prisma: public class Quader extends Prisma { // Zusaetzlich sind die Attribute Laenge und Breite der Grundflaeche // noetig: private double laenge; private double breite;
8 public Quader(double h, double l, double b) { super(h); laenge = l; breite = b; // Implementation der Operationen umfanggrundflaeche() und // inhaltgrundflaeche(): public double umfanggrundflaeche() { return 2 * (laenge + breite); public double inhaltgrundflaeche() { return laenge * breite; Die Klasse Zylinder als Unterklasse von Prisma: public class Zylinder extends Prisma { // Zusaetzlich ist das Attribute Radius Grundflaeche noetig: private double radius; public Zylinder (double h, double r) { super(h); radius = r; // Implementation der Operationen umfanggrundflaeche() und // inhaltgrundflaeche(): public double umfanggrundflaeche() { return 2 * radius * Math.PI; public double inhaltgrundflaeche() { return radius * radius * Math.PI; Die Klasse RegelmaessigesPrisma als Unterklasse von Prisma und Oberklasse für alle regelmäßigen Prismen: public class RegelmaessigesPrisma extends Prisma { // alle Grundflaechen regelmaessiger Prismen sind gleichseitige // Vielecke. Als zusaetzliches Attribut genuegt die Seitenlaenge: protected double seite; public RegelmaessigesPrisma(double h, double s) { super(h); seite = s;
9 Die Klasse RegelmaessigesSechsecksPrisma als Unterklasse von RegelmaessigesPrisma: public class RegelmaessigesSechsecksPrisma extends RegelmaessigesPrisma { public RegelmaessigesSechsecksPrisma(double h, double s) { super(s, h); // Implementation der Operationen umfanggrundflaeche() und // inhaltgrundflaeche(): public double umfanggrundflaeche() { return 6 * seite; public double inhaltgrundflaeche() { return 3 * seite * seite * Math.sqrt(3) / 2;
10 Aufgabe 10.4 [0 Punkte] (H) Vererbung Gegeben seien folgende Java-Klassen: class A { public void f ( ) { System. out. p r i n t l n ( f ( ) in A ) ; public void g ( ) { System. out. p r i n t l n ( g ( ) in A ) ; f ( ) ; class B extends A { public void f ( ) { System. out. p r i n t l n ( f ( ) in B ) ; public void h ( ) { System. out. p r i n t l n ( h ( ) in B ) ; f ( ) ; g ( ) ; class C extends A { public void h ( ) { System. out. p r i n t l n ( h ( ) in C ) ; f ( ) ; g ( ) ; interface I { public void m( ) ; abstract class D { public abstract void n ( boolean b ) ; public void o ( ) { System. out. p r i n t l n ( o ( ) in D ) ; n ( f a l s e ) ; class E extends D { public void n ( boolean b ) { System. out. p r i n t l n ( n ( ) in E ) ; i f ( b ) o ( ) ; public void m( ) { System. out. p r i n t l n ( m( ) in E ) ; c l a s s F extends E implements I { public void n ( boolean b ) { System. out. p r i n t l n ( n ( ) in F ) ; a) Folgende Anweisungen werden vom Compiler erfolgreich übersetzt: i) A a = new A();...................................... Richtig Falsch ii) B b = new B(); A t = b;........................... Richtig iii) B b = new A();...................................... Richtig Falsch Falsch iv) D d = new D();...................................... Richtig Falsch v) D d = new F();...................................... Richtig Falsch vi) F f = new F(); I i = f;........................... Richtig Falsch
11 b) Welche Ausgaben produzieren die folgenden Anweisungen? i) A a = new A(); a.g(); g() in A f() in A ii) B b = new B(); b.h(); h() in B f() in B g() in A f() in B iii) C c = new C(); c.g(); g() in A f() in A iv) B b = new B(); A a = b; a.g(); g() in A f() in B v) D d = new E(); d.n(true); n() in E o() in D n() in E vi) F f = new F(); f.o(); o() in D n() in F