Exercise index of this lecture   Alphabetic index   Course home   

Exercises and solutions
Design af klassehierarkier


8.1   Sammenlignelige bankkonti  

I forelæsningen studerede vi en abstrakt klasse Comparable, der definerer en ordning på objekter som er instanser af (subklasser af) Comparable. (Det er kun intentionen at kunne sammenligne objekter i samme klasse. Som bemærket i forelæsningsnoterne er dette svært at sikre statisk i Java).

Definer nu et Java Interface Comparable, som svarer til den abstrakte klasse Comparable. Interfacet Comparable skal altså have fire operationer: lessThan, lessThanOrEqual, greaterThan og greaterThanOrEqual.

Afprøv interfacet Comparable ved at definere en specialisering af klassen Konto, som implementerer interfacet Comparable. Specialiseringen skal hedde CompKonto. Vi antager at en konto k1 er mindre end k2 hvis saldoen af k1 er mindre end saldoen af k2. Specielt er kontoen k1 er lig med k2 (k1.equals(k2)) hvis de indeholder det samme beløb. Redefiner i den forbindelse equals i den nye Konto klasse.

Afprøv den specialiserede Konto klasse i et simpelt hovedprogram, som laver to Konto objekter og sammenligner disse med hinanden. Da mange sikkert ikke har tid til at lave et hovedprogram selv, kan I vælge at benytte mit hovedprogram. Dermed består opgaven altså I at lave interfacet og en Konto specialisering, som implementerer interfacet.

Solution
Her følger en løsning:

interface Comparable {
  boolean lessThan(Comparable other);
  boolean lessThanOrEqual(Comparable other);
  boolean greaterThan(Comparable other);
  boolean greaterThanOrEqual(Comparable other);
}

class Konto {
   protected double RenteSats = 0.02; // en static erklæring er mere naturlig
   protected String navn;
   protected double saldo;

   public Konto(String ejer) {
      navn = ejer; 
      saldo = 0;
   }

   public void hæv ( double beløb ) {
      saldo = saldo - beløb;
   }

   public void indsæt ( double beløb) {
      saldo = saldo + beløb;
   }         

   public void overførFra(double beløb, Konto fra) {
      fra.hæv(beløb);
      indsæt(beløb);
   } 

   public void tilskrivRente() {
      saldo = saldo + saldo * RenteSats;
   }

   public String toString() {
      return navn + "'s konto indeholder "
            + saldo + " kroner";
   }
} // Konto


class CompKonto extends Konto implements Comparable {

  public CompKonto(String nytNavn) {
    super(nytNavn);
  }

  // redefinition af equals fra klassen Object
  public boolean equals(CompKonto other){
    return (this.saldo == other.saldo);
  }

  public boolean lessThan(Comparable other){
    return (this.saldo < ((CompKonto)other).saldo);
  }

  public boolean lessThanOrEqual(Comparable other){
    return (this.lessThan(other) || this.equals((CompKonto)other));
    // NB: hvis vi ikke caster til CompKonto i equals bliver equals i Object aktiveret
    // Konsekvens af overloadning. Covarians får aldrig en chance
  }

  public boolean greaterThan(Comparable other){
    return (! this.lessThanOrEqual(other));
  }

  public boolean greaterThanOrEqual(Comparable other){
    return (! this.lessThan(other));
  }
}


public class KontoComparison {

   public static void main( String[] args ) {

     CompKonto konto1 = new CompKonto("Jens");
     CompKonto konto2 = new CompKonto("Peter");

     konto1.indsæt(600);
     konto2.indsæt(500);

     if (konto1.equals(konto2) )
       System.out.println("konto1 er lig med konto2");
     else
       System.out.println("konto1 IKKE lig med konto2");

     if (konto1.lessThan(konto2) )
       System.out.println("konto1 mindre end konto2");
     else
       System.out.println("konto1 IKKE mindre end konto2");

     if (konto1.lessThanOrEqual(konto2) )
       System.out.println("konto1 mindre end eller lig med konto2");
     else
       System.out.println("konto1 IKKE mindre end eller lig med konto2");

     if (konto1.greaterThan(konto2) )
       System.out.println("konto1 større end konto2");
     else
       System.out.println("konto1 IKKE større end konto2");

     if (konto1.greaterThanOrEqual(konto2) )
       System.out.println("konto1 større end eller lig med konto2");
     else
       System.out.println("konto1 IKKE større end eller lig med konto2");


   }
}

Her er endvidere et link til det rene Java program .


8.2   Iterator i cirkulær liste  

Denne opgave bygger endnu engang videre på opgaven om cirkulære lister, som vi har set på nogle gange under øvelserne i dette kursus. Det er naturligvis muligt at tage udgangspunkt i løsningen på denne opgave, enten jeres egen eller min løsning.

Udvid klassen CircularList med en operation elements, der returnerer en iterator for en cirkulær liste. Iteratoren skal være et objekt, der implementerer interfacet Enumeration. Det er tilladt at antage, at der ikke indsættes elementer i listen under et gennemløb.

Afprøv jeres nye CircularList klasse ved at gennemløbe en liste med brug af iteratoren.

Solution
Herefter følger en løsningsskitse. Vi inkluderer først Linkable og CircularList klasserne. Dernæst kommer klasen CircularListWithIterator. Bemærk, at vi laver en indre klasse CircularListIterator, som implementerer Enumeration. Denne klasse har en instansvariabel count, som på simpel vis holder styr på hvor mange elementer vi har gennemløbet. Man kunne undgå brug af en sådan varibel ved på en anden og mere tilfredsstillende måde at erkende, at man er nået hele vejen rundt i liste. Overvej dette. Tilsidst ser vi et program som laver en cirkulær liste med 99 heltal, hvorover vi itererer.

import java.util.*;

class Linkable {
  private Object data;
  private Linkable next;

  /** Return a Linkable object with null references in both data and next */ 
  Linkable(){
    data = null;
    next = null;
  }

  /** Return a Linkable object with null references in next, and the parameter as data */   
  Linkable(Object data){
    this.data = data;
    this.next = null;
  }

  /** Return a Linkable object with first parameter as data and second parameter as next */
  Linkable(Object data, Linkable next){
    this.data = data;
    this.next = next;
  }

  /** Return the data of this Linkable object */
  Object data(){
    return (data);
  }

  /** Return the reference to the next Linkable */
  Linkable next(){
    return (next);
  }

  /** Set the data field of this Linkable object */
  void setData(Object data){
    this.data = data;
  }

  /** Set the next field of this Linkable object */
  void setNext(Linkable next){
    this.next = next;
  }
} //Linkable


class CircularList {
  
  int length;
  Linkable last;

  /** return the first Linkable objekt in the circular list */
  private Linkable firstLinkable(){
   if (length != 0)
    return(last.next());
   else return(null);  //does not make sense
  }

  /** return the Linkable objekt just before last */
  private Linkable butLastLinkable(){
   if (length == 0)
     return(null);
   else {
     Linkable link = last;
     while (link.next() != last) link = link.next();
     return (link);
   }
  }

  /** arrange that I become empty */
  private void emptyMe(){
    length = 0;
    last = null;
  }

  /** Arrange that I am a circular list with el as the only element */
  private void makeMeSingular(Object el){
    last = new Linkable(el);
    last.setNext(last);    
    length = 1;
  }

  /** Construct an empty circular list */
  public CircularList(){
    this.emptyMe();
  }

  /** Return my number of elements */
  public int size(){
    return(length);
  }

  /** Insert el as a new first element */
  public void insertFirst(Object el){
    Linkable newLink;
    if (length == 0) {
      makeMeSingular(el);
    }
    else {
      newLink = new Linkable(el,firstLinkable());
      last.setNext(newLink);
      length = length + 1;
    }
  }
     
  /** Insert el as a new last element */
  public void insertLast(Object el){
    Linkable newLink;
    if (length == 0) {
      makeMeSingular(el);
    }
    else{
      Linkable rememberOldLast = last;
      newLink = new Linkable(el,firstLinkable());
      last = newLink;
      rememberOldLast.setNext(last);
      length = length + 1;
    }
  }

  /** Delete my first element */
  public void deleteFirst(){
    if (length <= 1)
      this.emptyMe();
    else{
      last.setNext(firstLinkable().next());
      length = length - 1;
   }
  }

  /** Delete my last element */
  public void deleteLast(){
    if (length <= 1)
       this.emptyMe();
    else {
      Linkable theFirst = firstLinkable();
      last = butLastLinkable();
      last.setNext(theFirst);
      length = length - 1;
    }
  }

  /** Return my first element if any. Else return null */
  Object retrieveFirst(){
    if (length >= 0)
       return(last.next().data());
    else return(null);
  }

  /** Return my last element if any. Else return null */
  Object retrieveLast(){
    if (length >= 0)
       return(last.data());
    else return(null);
  }

  /** Return my string representation */
  public String toString(){
    StringBuffer str = new StringBuffer();
    if (length == 0)
      return("Empty circular list");
    else {
      Linkable link = firstLinkable();
      str.append("CircularList[");
      for (int i = 1; i <= length; i++){
        str.append(link.data().toString() + ",");
        link = link.next();
      };
      str.append("]");
      return (str.toString());
    }
  }

} // CircularList

class CircularListWithIterator extends CircularList {

  class CircularIterator implements Enumeration {
    Linkable currentElement; // det element som iteratoren peger på
    int count;               // antallet af besøgte elementer

    CircularIterator (){
     count = 0; // vi har besøgt count elementer
     if (size() == 0)
       currentElement = null;
     else currentElement = last.next();  // altså det første element.
    }
    
    public boolean hasMoreElements(){
      return (count < size());
    }

    public Object nextElement(){
     if (currentElement != null){
       Object el = currentElement.data();
       currentElement = currentElement.next();
       count = count + 1;
       return(el);
     }
     else return(null);
    }
  } // end class CircularListIterator

  public CircularListWithIterator(){
    super();
  }

  Enumeration elements(){
    return (new CircularIterator());
  }
}  // CircularListWithIterator

public class IteratorCircularList {

  public static void main (String[] args){

    CircularListWithIterator cl = new CircularListWithIterator();

    for (int i = 1; i < 100; i++){
       cl.insertFirst(new Integer(i));
    }

    System.out.println(cl);

    for (Enumeration it = cl.elements(); it.hasMoreElements(); )
       System.out.println(it.nextElement());
 
  }

}
    

Her er endvidere et link til det rene Java program .


Generated: Monday March 31, 2008, 12:08:55
on the system cs-unix