Test 1 Übungen zu Softwareentwicklung 2 10.4.2003 Gruppe B Name: ___________________________________ Übungsleiter: __________ Tutor: ____________ Matrikelnummer: _________________________ Gruppe: _______________ Punkte: __________ Aufgabe 1: Klassen (8 Punkte) Die Klasse Ontology soll geordnete Mengen von Ontologieeinträgen verwalten. Beachten Sie, dass die Ontology jeden Eintrag maximal einmal (Gleichheit des Texts, Gross- und Kleinschreibung soll dabei irrelevant sein) enthält. Fügt man der Ontologie einen gleichen Eintrag ein zweites mal hinzu, bleibt die Ontologie unverändert. Beachten Sie weiters, dass die Liste immer geordnet verbleibt (auch nach dem Einfügen). Vervollständigen Sie das folgende Skelett der Klasse Ontology, indem Sie nur die vorgegebenen Kästchen ausfüllen. public class Ontology { private String[] entries = new String[256]; private int entriesCounter = 0; // Einträge in der Ontologie // akt. Anzahl der Einträge /* Fügt einen Eintrag zur geordneten Liste hinzu, wirft ListFullException(<string>), wenn keine neuen Einträge aufgenommen werden können */ public void add (String entry) throws ListFullException { if ((entry != null) && !containsEntry(entry)) { if (entriesCounter >= entries.length) { throw new ListFullException("Eintrag " + entry + " konnte nicht in die Ontology aufgenommen werden.");} for (int i = entriesCounter-1 ((i >= 0) && (entry.comparedToIgnoreCase(entries[i]) < 0))); i--) entries[i+1] = entries[i]; entries[i] = entries; entriesCounter++; } } /* Entfernt den Eintrag entry aus der geordneten Liste */ public void remove (Sring entry) { ... } /* True, wenn der Eintrag in der Ontology vorhanden ist */ public boolean containsEntry (String entry) { ... } Test 1 Übungen zu Softwareentwicklung 2 10.4.2003 Gruppe B Name: ___________________________________ Übungsleiter: __________ Tutor: ____________ Matrikelnummer: _________________________ Gruppe: _______________ Punkte: __________ /* Die Ontologie wird zur Schnittmenge aus sich selbst und der Ontologie ontology */ public void intersect(Ontology ontology) { for (int i = 0; i < entriesCounter; i++) { if (!ontology.contains(entries[i])) { remove(entries[i]); } } } /* Die Ontologie wird zur Vereinigungsmenge aus sich selbst und der Ontology ontology */ public void unite (Ontology ontology) { for (int i = 0; i < ontology.entriesCounter; i++) { add(ontology.entries[i]); } } } Anmerkung: • Die definierte Länge eines Arrays anArray kann mit <anArray>.length abgefragt werden. • Die Klasse String stellt folgende Objektmethode zur Verfügung: int compareToIgnoreCase(String str) Compares two strings lexicographically, ignoring case differences. returns: <0 when this is less than str; 0 when this is equal to str; >0 when this is greater than str Test 1 Übungen zu Softwareentwicklung 2 10.4.2003 Gruppe B Name: ___________________________________ Übungsleiter: __________ Tutor: ____________ Matrikelnummer: _________________________ Gruppe: _______________ Punkte: __________ Aufgabe 2: Vererbung (8 Punkte) Gegeben sei die folgende Klasse Vehicle, die Fahrzeugdaten verwaltet. public class Vehicle { private String name; private float maxSpeed; // Name des Fahrzeugs // maximale Geschwindigkeit in km/h public Vehicle (String aName, float aMaxSpeed) { name = aName; maxSpeed = aMaxSpeed; } public String getSpecification () { return "A " + name + " runs " + maxSpeed + " km/h max"; } } Leiten Sie davon eine Klasse Car ab, die zusätzlich zu dem noch den durchschnittlichen Verbrauch speichert. Implementieren Sie in Car einen Konstruktor und überschreiben Sie die Methode getSpecification so, dass Sie folgendes Ergebnis liefert: A <name> runs <maxSpeed> km/h max and consumes <consumption> l/100km z.B.: A sports car runs 350 km/h max and consumes 23.5 l/100km public class Car extends Vehicle private float consumption; { // Verbrauch in l/100km public Car (String aName, float aMaxSpeed, float aConsumption) { super(aName, aMaxSpeed); consumption = aConsumption; } public String getSpecification () { return super.getSpecification() + " and consumes " + consumption + " l/100 km"; } } Test 1 Übungen zu Softwareentwicklung 2 10.4.2003 Gruppe B Name: ___________________________________ Übungsleiter: __________ Tutor: ____________ Matrikelnummer: _________________________ Gruppe: _______________ Punkte: __________ Die Klasse Vendor verwendet die beiden Klassen Vehicle und Car. public class Vendor { public static void main (String[] args) { Vehicle[] vehicles = new Vehicles[] { new Vehicle("bicycle", 25), new Car("micro car", 45, 2.5) }; for (int i = 0; i < vehicles.length; i++) System.out.println(vehicles[i].getSpedification()); } } Welche Ausgabe produziert die main-Methode? A bicycle runs 25 km/h max A micro car runs 45 km/h max and consumes 2.5 l/100km Test 1 Übungen zu Softwareentwicklung 2 10.4.2003 Gruppe B Name: ___________________________________ Übungsleiter: __________ Tutor: ____________ Matrikelnummer: _________________________ Gruppe: _______________ Punkte: __________ Aufgabe 3: n o p q r s t u Dynamische Bindung (8 Punkte) abstract class Printer { public Printer () {}; public static int report () { ... } public abstract void print (); void prepare () { ... } public void doPrint () { print(); report(); } } abstract class NetPrinter extends Printer { String netAddr; public NetPrinter () { this("\\server1.tk.uni-linz.ac.at"); } public NetPrinter (String aNetAddr) { super(); netAddr = aNetAddr; } public void doPrint () { prepare(); super.doPrint(); Printer printerOne = new NetPrinter(); NetPrinter printerTwo = new NetPrinter(); printerOne.print(); printerTwo.print(); } public final int print () { ... } } Geben Sie durch Ankreuzen der entsprechenden Spalte in untenstehender Tabelle an, ob der jeweilige Aufruf (unterstrichen) bereits zur Übersetzungszeit (statisch) oder erst zur Laufzeit (dynamisch) an eine Implementierung gebunden werden kann. Begründen Sie Ihre Entscheidung kurz. Pos Stat Dyn Begründung n X print muss o p q X X X r s X t u X überschrieben werden Æ nur dyn. Bindung möglich statische Methoden Æ immer statisch gebunden Konstruktoren nicht vererbbar Æ immer statisch gebunden Supercalls von Konstruktoren Æ immer statisch gebunden X "normale" Methodenaufrufe in Java Æ dynamisch gebunden Supercalls Æ immer statisch gebunden X statischer Typ von printerOne ist Printer (= abstrakt) Æ muss also dynamisch gebunden werden statischer Typ von printerOne ist NetWriter und print ist in NetPrinter final, also ist Ziel in diesem Fall zur Übersetzungszeit bekannt Test 1 Übungen zu Softwareentwicklung 2 Gruppe B 10.4.2003 Name: ___________________________________ Übungsleiter: __________ Tutor: ____________ Matrikelnummer: _________________________ Gruppe: _______________ Punkte: __________ Aufgabe 4: Familie von Klassen und Polymorphismus (8 Punkte) Gegeben sei die folgende Klasse MenuPlan, die Gerichte (Products) eines Tagesmenüs ausgibt. Es soll dabei auch möglich sein Produkte, die aus weiteren Produkten zusammengesetzt sind (ComposedProducts) zu erstellen. Realisieren Sie die im Diagramm dargestellte Klassenfamilie. Das Dreieck ( ) symbolisiert dabei eine Vererbungsbeziehung, der Rhombus ( ) symbolisiert eine Aggregationsbeziehung. Vervollständigen Sie das folgende Skelett der Klassen, indem Sie nur die vorgegebenen Kästchen ausfüllen. Alle Gerichte (Product) sollen vor allem zwei Methoden, nämlich das Berechnen der Kalorien (calculateCalories) und die Rückgabe der Zusammensetzung (getComposition) zur Verfügung stellen. Aus Gründen der Wiederverwendbarkeit versuchen Sie möglichst viel "Code" in der Superklasse zu spezifizieren. Product public class MenuPlan { BasicProduct ComposedProduct public void main(String[] args) { ComposedProduct meal = new ComposedProduct ("Hauptspeise", ne Product[]{ new BasicProduct ("Grüner Salat", 120), new BasicProduct ("Wiener Schnitzl", 950), new BasicProduct ("Erbsenreis", 330)}; ComposedProduct completeMeal = new ComposedProduct ("Tagesmenue FR", new Product[]{meal, new BasicProduct ("Zwiebelsuppe", 80); new BasicProduct ("Zwetschkenkuchen", 150)}); System.out.println("Kalorienaufstellung: "+ completeMeal.getComposition()); } public abstract class Product { public String name; public Product() {this("neues Produkt");}; public Product(String name) { this.name = name; } public abstract float calculateCalories() ; public String getComposition() { return (name + " " + calculateCalories()); } Test 1 Übungen zu Softwareentwicklung 2 10.4.2003 Gruppe B Name: ___________________________________ Übungsleiter: __________ Tutor: ____________ Matrikelnummer: _________________________ Gruppe: _______________ Punkte: __________ extends Product public float calories; public class BasicProduct { public BasicProduct() { super(); this(0); }; public BasicProduct(String name, float calories) { super(name) this.calories = calories; } public class ComposedProduct extends Procduct { public Product[] productList; public ComposedProduct(String name, Product[] products) throws NullPointer Exception { if (items == Null) throw new NullPointerException; super(name); productList = products; } /* Berechnungen der Kalorien und Rückgabe der Zusammensetzung */ public float calculateCalories() { float sum = 0; for (int i = 0; i < productList.length; i++) { sum = sum + productList[i].calculateCalories(); } return sum + calories; } public void getComposition() { String composition = name + " " + calculateCalories(); for (int i = 0; i < productList.length; i++) { composition = composition + "\n" + productList[i].getComposition(); return composition; } Test 1 Übungen zu Softwareentwicklung 2 Gruppe B 10.4.2003 Name: ___________________________________ Übungsleiter: __________ Tutor: ____________ Matrikelnummer: _________________________ Gruppe: _______________ Punkte: __________ Aufgabe 5: Interfaces und Kontrakte (8 Punkte) Graphische Buttons der Java Klassenbibliothek senden ein ActionEvent (spezieller Typ von java.util.EventObject) aus, wenn mit der Maus auf den Button geklickt wird. Vervollständigen Sie folgende Programmcodestücke, welche eine Registrierung für den Empfang von ActionEvents implementieren sollen (bei einem Klick soll „Button clicked“ ausgegeben werden): Ereignistyp: class ActionEvent { extends java.util.EventObject public ActionEvent(Object source) { super(source); } } Schnittstelle des Ereignisempfängers: public interface ActionListener extends java.util.EventListener { public void actionPerformed (ActionEvent event); } Konkreter Ereignisempfänger: class AnActionListener implements ActionListener { public void actionPerformed(ActionEvent event ) { System.out.println(“Button clicked”); } } Registrierung des Ereignisempfängers: ... AnActionListener listener = new AnActionListener(); Button button = new Button("Click me"); button.addActionListener( listener );