// Liitetään tiedosto pakkaukseen. package nisakkaat; /* * Olio-ohjelmoinnin perusteet I. * * Yksinkertainen nisäkästä mallintava abstrakti yliluokka, jonka konkreettisia * jälkeläisiä voi vertailla toisiinsa. * * Jorma Laurikkala (jorma.laurikkala@tuni.fi). * * Viimeksi muutettu 5.2.2020. * */ public abstract class Nisakas implements Comparable { /* * Vakiomuotoiset attribuutit. * */ // Tarkoitettu käytettäväksi jälkeläisten toString-metodeissa. protected final String EROTIN = ", "; /* * Kaikille nisäkkäille yhteiset tiedot ilmentymäattribuutteina. * */ // true = elää, false = edesmennyt. private boolean elossa; // Nisäkkään paino (> 0) kiloina. private double paino; /* * Rakentajat. * */ /* * Luodaan elävä nisäkäs, joka painaa 100 g. */ public Nisakas() { elossa = true; paino = 0.1; } /* * Parametrillinen rakentaja, jonka parametreilla määritellään nisäkkään * elämä (e) ja paino (kg). Paino asetetaan vain, jos se on sallittu. */ public Nisakas(boolean e, double kg) { elossa(e); paino(kg); } /* * Kaikille nisäkkäille yhteisiä toimintoja luokkametodeina. * */ /* * Palauttaa lajimuistiin tallentuneen tiedon siitä onko toinen olio uhkaava. * Oletetaan, että nisäkäs on oletusarvoisesti varovainen, jos toinen olio * on olemassa. */ public static boolean onkoUhka(Object toinen) { if (toinen != null) { return true; } else { return false; } } /* * Aksessorit. * */ public boolean elossa() { return elossa; } public void elossa(boolean e) { elossa = e; } public double paino() { return paino; } public void paino(double kg) { if (kg > 0) { paino = kg; } } /* * Kaikille nisäkkäille yhteisiä toimintoja ilmentymämetodeina. * */ /* * Syömistä, jota konkreettisen aliluokan on pakko tarkentaa toteuttamalla * tämä metodi. */ public abstract void syö(); /* * Oletetaan suurin osa nisäkkäistä "pieniksi". */ public boolean onkoIso() { return false; } /* * Object-luokan korvatut metodit. * */ @Override public String toString() { // Selvitetään olion luokan nimi ilman pakkausta reflektion avulla. String luokanNimi = getClass().getSimpleName(); // Muodostetaan merkkijonoesitys. Object-luokan metodia ei kutsuta, // jotta esitys pysyisi selkeämpänä. return luokanNimi + ": " + elossa + EROTIN + paino; } /* * Poikkeus käsitellään metodissa, koska metodi ei saa heittää poikkeusta. * Metodi voidaan toteuttaa myös siten, että try-catch-lausetta ei tarvita. * Object-luokan versiota _ei_ kutsuta, koska siinä vertaillaan olioiden * tietojen sijasta viitteitä, jolloin metodi käyttäytyy kuin * yhtäsuuruusoperaattori (==). */ @Override public boolean equals(Object obj) { try { // Asetetaan olioon Nisakas-luokan viite, jotta voidaan kutsua // Nisakas-luokan aksessoreita. Nisakas toinen = (Nisakas)obj; // Oliot ovat samat, jos attribuuttien arvot ovat samat. return (elossa == toinen.elossa()) && (paino == toinen.paino()); } catch (Exception e) { return false; } } /* * Muodostetaan hajautuskoodi kääreluokkien metodien avulla Josh Blochin * menetelmää käyttäen. */ @Override public int hashCode() { int tulos = 17; tulos = 31 * tulos + Boolean.hashCode(elossa); tulos = 31 * tulos + Double.hashCode(paino); return tulos; } /* * Comparable-rajapinnan metodin toteutus. * */ /* * Korvataan Comparable-rajapinnan ainokainen metodi. Geneerinen tyyppi T * on kiinnitetty Nisakas-tyypiksi. Palauttaa arvon nolla aina, kun equals * palauttaa true-arvon. */ @Override public int compareTo(Nisakas toinen) { // Tämä olio < parametrina saatu olio. if (paino < toinen.paino()) { return -1; } // Tämä olio == parametrina saatu olio. else if (paino == toinen.paino()) { return 0; } // Tämä olio > parametrina saatu olio. else { return 1; } } }