Svar och lösningar till tentamen 140602

del 1

1) A: Proxy    B: Strategy     C: Facade    D: Iterator     E: Template Method
 
2)     CSC
* vid Wit anger att en Doer kan ha många objekt av Wit. Det syns i koden på att Wit har en ArrayList med Wit-objekt.

3) Mönstret är Observer. Klassen Doer motsvarar Observable (eller Subject) i standardbeskrivningen av mönstret. Observer i standardbeskrivningen motsvaras av interfacet Wit (witness) i uppgiften. Varje Doer har en lista av Wit–objekt och sådana kan läggas till och tas bort med metoderna tie() och untie(). Metoden tell() i Doer ser till att alla Wit–objekt uppdateras genom att deras refresh() anropas. tell() och refresh() i uppgiften motsvaras av notify() och update() i standardbeskrivningen.

Standard Uppgift 2
Observable Doer
attach() tie()
detach() untie()
notify() tell()
Observer Wit
update() refresh()

4a) 1) I XP används testdriven programutveckling. Man testar koden väldigt väldigt ofta. Vattenfallsmetodiken har en testfas sent i projektet. 2) XP är en iterativ metodik där kraven kan ändras många gånger under projektets gång. I Vattenfallsmetodiken planerar man allt från början.
4b) Det finns många att välja på: Parprogrammering, kundnärvaro i projektet, "the planning game", enklast möjliga design, alla i projektet äger koden.

5a) B: RUN REST RUN
Objektets typ bestämmer vilken metod som körs.
Objekten är av typ Athlete, Person, Athlete.
5b) Alternativ A är fel. Ett godtyckligt objekt av typ Object kan inte inta platsen som Person. En Person förväntas t.ex. ha metoden activity() och det har ju inte alla som är Object.

6a) Man skriver metoden equals(Point p) i klassen Point så att den returnerar true om Point–objekten har samma x-koordinat och samma y-koordinat. (Även metoden hashCode() måste definieras om så att samma värde returneras men det krävs inte i svaret för att få full poäng.)

6b) Klassen Point ska implementera Java-interfacet Comparable<Point>. Det innebär att Point ska ha en metod compareTo(Point otherP) som jämför de två punkternas x-koordinater och returnerar 0 om punkterna har samma x, negativt om första punkten har lägre värde och returnerar positivt annars.

Javakod krävs inte för full poäng på uppgift 6, förutsatt att svaren tydligt beskriver vad som ska gälla. Här kommer ändå kodförslag.

class Point implements Comparable<Point> {
    int x;
    int y;

    Point (int ix, int iy) {
         x = ix; y = iy;
    }

    public boolean equals (Point otherP) {
        return x == otherP.x && y == otherP.y;
    }

    public int hashCode() {
        return  // Definiera listig hashkod baserad på x och y   
    }

    public int compareTo (Point otherP) {
        return otherP.x - x;                // ger < 0 om this kommer först
    }                                       // ger 0   om lika
}                                           // ger > 0 om otherP kommer först

7) Påståendena C, E och F är korrekta.

del 2

8a) Variabeln spell i klassen Mystery är en klassvariabel. Det betyder att det finns en enda variabel spell i klassen, inte en för varje objekt av Mystery. Varje gång ett objekt av Mystery skapas sker en ny tilldelning till den gemensamma variabeln spell. toString() returnerar värdet av den enda variabeln spell. Om ordet static stryks som modifierare till spell kommer klassen att fungera som väntat och varje objekt har ett eget spell-värde.

8b) Om utskrift av m1 görs direkt efter Mystery m2 = new Mystery(666); kommer värdet 666 att skrivas.

8c) Satsen System.out.println(spell) fungerar bra inom klassen Mystery när spell är static. När static strukits går det inte bra längre. Det räcker att svara att det går bra för att få 1p.

9) Dynamisk bindning: I en superklass A, definieras en abstrakt metod m(). Definiera subklasser till A, definiera om metoden m() i varje subklass. Via referenser av typ A kan metoden m() anropas även för objekt av alla subklasser. Det är då subklassens typ som bestämmer vilken metod m() som exekveras, alla subklasserna har ju olika varianter. När anropet a.m(); kompileras går det inte att avgöra vilken metod som ska exekveras, a kan refera till objekt av godtycklig subklass till A. Det avgörs under programmets körning, dynamiskt.

Polymorfism: Ojbekt av alla subklasser till A "är A" och alla har metoden m(). Men objekten är olika och beter sig olika (subklasserna har olika implementationer av m()). A är mångformig, polymorf.

 

10a) Man använder ett interface som har en enda metod. Metoden bör ha returtyp boolean och används vid filtreringen. De konkreta villkoren anges i implementerande klasser. Metoden som filtrerar en lista tar två parametrar: 1) listan som ska filtreras och 2) ett objekt av interfacetypen. Samma princip som t.ex. sorteringsmetoden i klassen Collections används. Så här kan interfacet se ut:

interface Filter<E> {
    public boolean cond (E e);
}
En filtreringsmetod utan typparameter, som funkar på allt som kan refereras med Object-referenser kan se ut så här:
static void filter(ArrayList alist, Filter fil) {
    Iterator it = alist.iterator();
    while (it.hasNext())
        if (fil.cond(it.next()))          // Objekt som uppfyller filtreringsvillkoret 
            it.remove();                  // tas bort ur listan på säkert sätt
}                                         // via iteratorn
Metoden ovan ändrar den lista som ges som parameter (precis som Collections.sort() gör). Det går förstås att skriva metoden så att den returnerar den filtrerade listan. Metoden ovan kommer att ge varningsmedelanden vid kompilering därför att den inte använder typparametrar fullt ut.

Vi har inte tagit upp typparametrisering så mycket i kursen att en fullständigt typparametriserad filtermetod kan förväntas som svar så denna betraktas som överkurs för den som är extra intresserad: filter2

10b) I det konkreta fallet där element i listan är texter och man filtrerar på texternas längd så anropas metoden filter() ovan med aktuell String–lista samt med ett objekt av en implementation av interfacet Filter ovan. Implementationen kan se ut så här.

class MyFilter implements Filter<String> {
    int n;
    MyFilter(int n) {
        this.n = n;
    }

    public boolean f(String s) {
        return s.length() < n;
    }
}
och anropet som utför filtreringen:
filter(alist, new MyFilter(13));
Anropet ovan rättades 13 juni. Tidigare antogs att metoden filter returnerar en lista istället för att ändra sin parameter.

 

11a) CSC

11b)

import java.util.*;
abstract class Decorator implements IQueue<String> {

    IQueue<String> myq;

    Decorator(IQueue<String> q) {
        myq = q;
    }

    public boolean isEmpty() {
        return myq.isEmpty();
    }

    public void put(String s) {
        myq.put(s);
    }

    public String get() {
        return myq.get();
    }
}

11c)

import java.util.*;
class SizeDeco extends Decorator {
    private int qsize;
    
    SizeDeco (IQueue<String> myQ) {
        super(myQ);
        ArrayList<String> helper = new ArrayList<String>();
        while (! super.isEmpty()) {
	    helper.add(super.get());
        }
        qsize = helper.size();
        for (String s : helper)
	    super.put(s);
    }

    public void put(String s) {
        qsize++;
        super.put(s);
    }

    public String get(){
        if (!super.isEmpty()) {
            qsize--;
            return super.get();
        }
        return null;
    }

    public int size() {
        return qsize;
    }
}

11d)

import java.util.*;
class FilterDeco extends Decorator {
    
    FilterDeco (IQueue<String> myq) {
        super(myq);
    }

    public void removeAll(){
    while (!super.isEmpty())
        super.get();
    }

    // Filter antas vara ett interface med en boolean-metod
    // som anger villkoret för filtreringen

    public void filter(Filter filter) {
    ArrayList<String> helper = new ArrayList<String>();
        while (! super.isEmpty()) {
            String s = super.get();
            if (filter.cond(s))        // Filter-interfacets metod anropas
               helper.add(s);          // utan att vi vet vilken filtrering
        }                              // som är aktuell
        for (String s:helper)
            super.put(s);
    }
}