5.7. Ekstra eksempler

Dette afsnit giver nogle ekstra eksempler, der repeterer stoffet i kapitlet.

5.7.1. En n-sidet terning

Det normale er en 6-sidet terning, men der findes også 4-, 8- 12- og 20-sidede. Klassen nedenfor beskriver en generel n-sidet terning.

Vi har ladet antallet af sider og værdien være private, og lavet metoden hentVærdi(), som kan bruges udefra. Der er også en sætVærdi()-metode, mens antallet af sider ikke kan ændres udefra, når først terningen er skabt.

Figur 5-6. Java

// En n-sidet terning.
public class NSidetTerning
{
  // hvor mange sider har terningen (normalt 6)
  private int sider;

  // den side der vender opad lige nu
  private int værdi;

  // konstruktør opretter normal terning med 6 sider
  public NSidetTerning ()
  {
    sider = 6;
    kast(); // sæt værdi til noget
  }

  // opretter terning med et vist antal sider
  public NSidetTerning (int antalSider)
  {
    if (antalSider >= 3) sider = antalSider;
    else sider = 6;
    kast();
  }

  // metode der kaster terningen
  public void kast ()
  {
    // find en tilfældig side
    double tilfældigtTal = Math.random();
    værdi = (int) (tilfældigtTal * sider + 1);
  }

  // giver antallet af øjne på siden der vender opad
  public int hentVærdi ()
  {
    return værdi;
  }

  // sætter antallet af øjne der vender opad
  public void sætVærdi (int nyVærdi)
  {
    if (nyVærdi > 0 && nyVærdi <= sider) værdi = nyVærdi;
    else System.out.println("Ugyldig værdi");
  }

  // giver en strengrepræsentation af terningen
  // hvis den ikke har 6 sider udskrives også antal af sider
  public String toString ()
  {
    String svar = ""+værdi;  // værdi som streng, f.eks. "4"
    if (sider!= 6) svar= svar+"("+sider+"s)";
    return svar;
  }
}

Her er et program til at afprøve klassen med:

public class BenytNSidetTerning
{
  public static void main(String args[])
  {
    NSidetTerning t = new NSidetTerning(); // sekssidet terning

    System.out.println("t viser nu "+t.hentVærdi()+" øjne");

    NSidetTerning t6 = new NSidetTerning(6); // sekssidet terning
    NSidetTerning t4 = new NSidetTerning(4); // firesidet terning
    NSidetTerning t12 = new NSidetTerning(12); // tolvsidet terning

    System.out.println("t4 er "+t4); // t4.toString() kaldes implicit
    t4.kast();
    System.out.println("t4 er nu "+t4);
    t4.kast();

    System.out.println("terninger: "+t+" "+t6+" "+t4+" "+t12);
    t.kast();
    t12.kast();
    System.out.println("terninger: "+t+" "+t6+" "+t4+" "+t12);

    for (int i=0; i<5; i++) 
    {
      t.kast();
      t6.kast();
      t4.kast();
      t12.kast();
      System.out.println("kast "+i+": "+t+" "+t6+" "+t4+" "+t12);
      if (t.hentVærdi() == t6.hentVærdi())
      {
        System.out.println("t og t6 er ens!");
      }
    }
  }
}
t viser nu 6 øjne
t4 er 4(4s)
t4 er nu 1(4s)
terninger: 6 1 4(4s) 5(12s)
terninger: 6 1 4(4s) 3(12s)
kast 0: 3 1 4(4s) 2(12s)
kast 1: 1 6 4(4s) 11(12s)
kast 2: 1 1 4(4s) 5(12s)
t og t6 er ens!
kast 3: 3 6 4(4s) 3(12s)
kast 4: 3 2 2(4s) 6(12s)

5.7.2. Personer

Lad os lave en klasse til at repræsentere en person. Hvert person-objekt skal have et fornavn, et efternavn og en alder. Når man opretter en ny Person, skal man angive disse data, f.eks.: new Person("Jacob","Nordfalk",30), så vi definerer en konstruktør med disse parametre.

Vi definerer også, at hver person har metoden toString(), der returnerer en streng med personens oplysninger af formen "Jacob Nordfalk (30 år)".

Desuden har vi metoden præsentation(), der skriver oplysningerne pænt ud til skærmen som "Jeg hedder Jacob og jeg er 30 år". Denne metode returnerer ikke noget, men skriver i stedet hilsenen ud til skærmen (personer under 5 år siger bare "agyyy!")

Til sidst kunne man forestille sig, at en person kan hilse på en anden person (metoden hils()). Det afhænger af alderen hvordan man hilser. En person på over 60 år vil hilse på Jacob med "Goddag hr Nordfalk", mens en yngre bare vil sige "Hej Jacob".

import java.util.*;
public class Person
{
  public String fornavn;
  public String efternavn;
  public int alder;
  public Vector konti; // bruges senere

  public Person(String fornavnP, String efternavnP, int alderP)
  {
    fornavn = fornavnP;
    efternavn = efternavnP;
    alder = alderP;
    konti = new Vector(); // bruges senere
  }

  public String toString()
  {
    return fornavn+" "+efternavn+" ("+alder+" år)";
  }

  public void præsentation()
  {
    if (alder < 5) System.out.println("agyyy!");
    else System.out.println("Jeg hedder "+fornavn+", og jeg er "+alder+" år.");
  }

  public void hils(Person andenPerson)
  {
    if (alder < 5) System.out.print("ma ma.. ");
    else if (alder < 60) System.out.print("Hej "+andenPerson.fornavn+". ");
    else  System.out.print("Goddag hr. "+andenPerson.efternavn+". ");

    præsentation();
  }
}

Bemærk, at Person-objektet har to andre objekter, nemlig to strenge. Selvom man ikke plejer at tegne strenge med i klassediagrammer, har vi alligevel taget dem med for at illustrere, at der faktisk også eksisterer en har-en-relation mellem disse to klasser.

Figur 5-7. En Person har to String-objekter. Disse er undtagelsesvist også vist

Læg også mærke til, hvordan vi fra hils()-metoden kalder præsentation(). Lad os prøve at oprette tre personer og lade dem præsentere sig og derpå hilse på hinanden:

public class BenytPerson
{
  public static void main(String args[])
  {
    Person x, y, z;
    x = new Person("Jacob", "Nordfalk", 30);
    y = new Person("Kai", "Lund", 86);
    z = new Person("Peter", "Holm", 2);

    System.out.println("Vi har oprettet "+x+", "+y+" og "+z);
    x.præsentation();
    y.præsentation();
    z.præsentation();
    x.hils(y);
    y.hils(x);
    z.hils(x);
  }
}
Vi har oprettet Jacob Nordfalk (30 år), Kai Lund (86 år) og Peter Holm (2 år)
Jeg hedder Jacob, og jeg er 30 år.
Jeg hedder Kai, og jeg er 86 år.
agyyy!
Hej Kai. Jeg hedder Jacob, og jeg er 30 år.
Goddag hr. Nordfalk. Jeg hedder Kai, og jeg er 86 år.
ma ma.. agyyy!

I linjen

    x.hils(y);

er det x-variablens person (Jacob), der hilser på y-variablens person. Da x-variablens person er under 60, vil den uformelle hilsen "Hej Kai" blive brugt. I linjen under er det lige omvendt.

5.7.3. Bankkonti

Lad os se nærmere på relationer mellem objekter i bankverdenen. De vigtigste egenskaber ved en bankkonto er saldoen, og hvem der ejer den. Et Konto-objekt kunne altså have et Person-objekt tilknyttet, en har-en-relation, og denne person bør være kendt, når kontoen oprettes. Det er derfor oplagt, at ejeren skal angives i Konto's konstruktør. Kontoen skal også sørge for at indsætte sig selv (her bruges nøgleordet this) i personens liste over konti, sådan at der er konsistens mellem data i Konto-objektet og data i Person-objektet.

public class Konto
{
  public int saldo;
  public Person ejer;

  public Konto(Person ejeren)
  {
    saldo = 0;
    ejer = ejeren;               // Sæt kontoen til at referere til personen
    ejer.konti.addElement(this); // ..og personen til at referere til kontoen
  }

  public void overførsel(int kroner)
  {
    saldo = saldo + kroner;
  }

  public String toString()
  {
    return ejer+" har "+saldo+" kroner";
  }
}

Figur 5-8. Java

En Konto har altid en Person tilknyttet

Dette er et eksempel på en har-en-relation begge veje. Læg mærke til, hvordan vi fra Konto-objektet får fat i listen af ejerens konti. Den tilføjer vi så kontoen selv - this - til:

    ejer.konti.addElement(this);