// Liitetään tiedosto pakkaukseen. package nisakkaat; /* * Olio-ohjelmoinnin perusteet I. * * Abstraktista nisäkkäästä peritty konkreettinen kissaa mallintava luokka, * joka osaa tervehtiä, esitellä itsensä merkkijonona ja vertailla. * * Jorma Laurikkala (jorma.laurikkala@tuni.fi). * * Viimeksi muutettu 5.2.2020. * */ public class Kissa extends Nisakas implements Tervehtiva { /* * Vakiomuotoiset luokka-attribuutit. * */ // Elämien lukumäärän yläraja. public static final int MAXELOT = 9; /* * Luokka-attribuutit. * */ // Tosi, jos kissat haukottelevat. private static boolean haukottelee; /* * Ilmentymäattribuutit. * */ // Kissan väri. private String väri; // Kissan hännän tyyppi (esimerkiksi "kippura"). private String häntä; /* * Rakentajat. * */ /* * Kissa-luokan oletusrakentajassa kissaolion väriksi asetetaan musta * ja hännän tyypiksi kippura. */ public Kissa() { väri = "musta"; häntä = "kippura"; } /* * Parametrillinen rakentaja, jossa kissalle asetetaan ulkoisen tahon * määrittelemä väri (v) ja häntä (h). Annettu arvo asetetaan vain, * jos se on sallittu. */ public Kissa(String v, String h) { // Koodia lyhennetty aksessoreita kutsumalla, jolloin tarvitaan vähemmän // if-lauseita. väri(v); häntä(h); } /* * Parametrillinen rakentaja, jossa kissalle asetetaan seuraavat tiedot: * e = onko kissa elossa, kg = kissan paino, v = kissan väri ja h = hännän * tyyppi. Annettu arvo asetetaan vain, jos se on sallittu. */ public Kissa(boolean e, double kg, String v, String h) { // Kutsutaan yliluokan rakentajaa, jolloin koodia ei tarvitse monistaa // aliluokkaan. super(e, kg); // Vältetään koodin toistoa aksessoreita. väri(v); häntä(h); } /* * Luokkametodit. * */ /* * Palauttaa lajimuistiin tallentuneen tiedon siitä onko toinen olio uhkaava. * Oletetaan, että kissa säikähtää aina, myös itseään. Yliluokan versio * luokkametodista ei korvaudu, vaan peittyy. */ public static boolean onkoUhka(Object toinen) { return true; } /* * Ilmentymämetodit. * */ private void hairikoi() { // Tavaroita hajoaa... } public String väri() { return väri; } public void väri(String v) { if (v != null && v.length() > 0) { väri = v; } } public String häntä() { return häntä; } public void häntä(String h) { if (h != null && h.length() > 0) { häntä = h; } } public boolean haukottelee() { return haukottelee; } public void haukottelee(boolean h) { haukottelee = h; } /* * Tulostetaan parametrina annettu ääniefekti. */ public void ääntele(String s) { System.out.println(s); } /* * Tulostetaan parametrina annettu ääniefekti k kertaa. */ public void ääntele(String s, int k) { for (int i = 0; i < k; i++) { ääntele(s); } } /* * Kissa sanoo näin tyytyväisenä. */ public void kehrää() { ääntele("murr, murrrr..."); } /* * Korvatut ilmentymämetodit. * */ /* * Karkea sääntö kissan koon arviointiin. */ @Override public boolean onkoIso() { return paino() > 10; } /* * Toteutetut ilmentymämetodit. * */ /* * Kissamaista syömistä. Yliluokan metodin toteutus. */ @Override public void syö() { System.out.println("Syön kuin kissa..."); kehrää(); } /* * Kissamainen moi. Rajapinnan metodin toteutus. */ @Override public void moikkaa() { System.out.println("Miu! Pusken jalkaa..."); } /* * Object-luokan korvatut metodit. * */ @Override public String toString() { // Yhdistetään kissan tiedot yliluokan tietojen perään. return super.toString() + EROTIN + väri + EROTIN + häntä; } @Override public boolean equals(Object obj) { try { // Asetetaan olioon Kissa-luokan viite, jotta voidaan kutsua // Kissa-luokan aksessoreita. Kissa toinen = (Kissa)obj; // Oliot ovat samat, jos luokan ja sen yliluokan attribuuttien // arvot ovat samat. Huomaa, että arvoja vertaillaan String- // luokassa korvatulla equals-metodilla. return super.equals(obj) && väri.equals(toinen.väri()) && häntä.equals(toinen.häntä()); } catch (Exception e) { return false; } } @Override public int hashCode() { // Aloitetaan yliluokan tiedoista lasketulla koodilla. int tulos = super.hashCode(); // Jatketaan aliluokan tiedoilla ja Josh Blochin menetelmällä null-arvot // huomioiden. tulos = 31 * tulos + (väri == null ? 0 : väri.hashCode()); tulos = 31 * tulos + (häntä == null ? 0 : häntä.hashCode()); /* * Yllä käytetään if-else-lauseen asemasta kolmioperandista valintaoperaattoria. * Ensimmäinen operandi on totuusarvon palauttava ehtolauseke. Operaattorin * tulos on toinen operandi, jos ehtolausekkeen tulos on true, muuten tulos on * kolmas operandi. Lause: * * tulos = 31 * tulos + (väri == null ? 0 : väri.hashCode()); * * on tuttuna if-else-lauseena: * * if (väri == null) { * tulos = 31 * tulos + 0; * } * else { * tulos = 31 * tulos + väri.hashCode()); * } * * Käytä valintaoperaattoria maltillisesti, koska se pidentää lauseita * ja monimutkaistaa niitä. Operaattori on laskentajärjestyksen hännillä. * Se tulee sulkea sulkeisiin muun muassa, jos sitä edeltää tai seuraa * aritmeettinen operaattori. */ // Palautetaan tulos. return tulos; } }