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()); }