Jos Javassa ei peritä luokkaa mistään, niin se periytyy aina Object-luokasta. Näin siksi, että kaikki oliot saadaan samaan hierarkiaan ja voidaan esimerkiksi tallentaa samaan tietorakenteeseen. Käytännössä tämä ei ole kovin kätevää, sillä silloin tietorakenteessa olevilla olioilla on käytössä vain Object-luokan metodit. Jotta olioilla voitaisiin tehdäkin jotakin, pitää niiden tyyppi muuntaa vastaamaan niiden varsinaista luokkaa.
Object-luokassa on kuitenkin muutama tärkeä metodi, joiden olemassa olosta ohjelmoijan on hyvä olla tietoinen:
Object clone(); // tekee oliosta itsestään kopion boolean equals(Object obj); // vertaa oliota toiseen olioon int hashCode(); // palauttaa olioon liityvän "lajitteluavaimen" String toString(); // palauttaa olion merkkijonona
/**
* Luokka toteuttamaan sovitun julkisen rajapinnan ja Object-
* luokan metodeja.
* @author Vesa Lappalainen
* @version 1.0, 01.02.2003
*/
public class AikaF implements AikaRajapinta {
private int h, m;
/**
* Asettaa uuden ajan ja pitää huolen että aika on aina oikeaa muotoa.
* @param h asetettavat tunnit
* @param m asetettavat minuutit
*/
public void aseta(int h,int m) {
this.h = h; this.m = m; lisaa(0);
}
public AikaF() { this.h = 0; this.m = 0; }
/**
* Asettaa uuden ajan ja pitää huolen että aika on aina oikeaa muotoa.
* @param h asetettavat tunnit
*/
public AikaF(int h) {
aseta(h,0);
}
/**
* Alustaa ajan
* @param h tunnit
* @param m minuutit
*/
public AikaF(int h,int m) { // Muodostaja
aseta(h,m);
}
/**
* Tulostaa ajan muodossa 15:05
* @param lf tulostetaanko rivinvaihto vai ei
*/
public void tulosta(boolean lf) {
System.out.print(toString());
if ( lf ) System.out.println();
}
/**
* Tulostaa ajan muodossa 15:05 sekä aina rivinvaihdon
*/
public void tulosta() {
tulosta(true);
}
/**
* Lisää aikaan valitun minuuttimäärän
* @param lisa_min lisättävä minuuttimäärä
*/
public void lisaa(int lisa_min) {
int yht_min = h * 60 + m + lisa_min;
h = yht_min / 60;
m = yht_min % 60;
}
public static void lisaa(AikaF aika,int lisa_min) {
int yht_min = aika.h * 60 + aika.m + lisa_min;
aika.h = yht_min / 60;
aika.m = yht_min % 60;
}
public int getH() { return h; }
public int getM() { return m; }
public String toString() {
return "" + h + ":" + (m<10?"0":"")+m;
}
public boolean equals(Object o) {
if ( !(o instanceof AikaRajapinta) ) return false;
AikaRajapinta a = (AikaRajapinta)o;
return getH() == a.getH() && getM() == a.getM();
}
public Object clone() {
return new AikaF(getH(),getM());
}
public int hashCode() {
return 3600*getH() + 60*getM();
}
public static void main(String[] args) {
AikaF a1 = new AikaF();
AikaF a2 = new AikaF(13);
AikaF a3 = new AikaF(14,25);
a1.tulosta(); a2.tulosta(); a3.tulosta();
a1.aseta(12,15); a2.aseta(16,-15);
a1.tulosta(); a2.tulosta();
lisaa(a1,55); a1.tulosta();
System.out.println("Tunnit = " + a1.getH());
System.out.println(a1.toString());
}
}
Esimerkiksi tekemällä metodi
public String toString() {
return "" + h + ":" + (m<10?"0":"")+m;
}
vältämme kaikki tulostukseen liittyvät ongelmat. Jos halutaan verrata kahta Aika-oliota keskenään, kannattaa kirjoittaa equals-metodi.
public boolean equals(Object o) {
if ( !(o instanceof AikaRajapinta) ) return false;
AikaRajapinta a = (AikaRajapinta)o;
return getH() == a.getH() && getM() == a.getM();
}
equals-metodia kirjoitettaessa on oltava huolellinen, sillä parametrina saattaa tulla oikean tyyppinen olio tai sitten väärän tyyppinen olio. equals-metodin pitää toteuttaa seuraavat ominaisuudet:
Olkoon seuraavassa a1,a2 ja a3 kolme luokan oliota. reflektiivisyys: a1.equals(a1) pitää olla aina tosi symetrisyys: a1.equals(a2) == a2.equals(a1) transitiivisuus: a1.equals(a2) = true; a2.equals(a3) = true; => a1.equals(a3) = true; luonnollisesesti toistuvien equals kutsujen pitää palautta samoille olioille sama arvo, mikäli olioiden samuuteen vaikuttava tila ei muutu
Jos luokkaan toteutetaan equals-metodi, on siihen toteutettava myös hajautusarvo. Javan tietorakenteet tarvitsevat hajautusarvoa. Hajautusarvon täytyy palauttaa sama luku olioille, jotka ovat equals-vertailussa saman arvoisia. Mutta kaksi eriarvoistakin oliota saa palauttaa saman hajautusarvon. Meidän tapauksessamme hajautusarvoksi voidaan valita vaikkapa sekunnit vuorokauden alusta:
public int hashCode() {
return 3600*getH() + 60*getM();
}
Lisäksi monessa tilanteessa tarvitaan oliosta samanlainen kopio. Tätä varten toteutetaan clone-metodi:
public Object clone() {
return new AikaF(getH(),getM());
}