Table of Contents
Polymorfismus, dědičnost - Geometrické obrazce
Polymorfismem rozumíme techniku, kdy očekáváme, že jeden objekt dokáže zastoupit druhý. Tzn. že dokáže odpovědět na nějakou sadu zpráv.
Nechť máme sadu grafických objektů, např. pro plotter. Chceme od každého objektu vědět, kolik na něj spotřebujeme inkoustu, tj. jeho obvod. Ale je nám jedno, co je objekt zač. Nezajímá nás, jestli je to kruh nebo čtverec, chceme od něj jen ten obvod. Takže pošleme zprávu obvod
(zavoláme metodu obvod
) a očekáváme, že každý objekt v kolekci reprezentující naši scénu nám odpoví.
Polymorfismus lze v Javě kvůli typové kontrole při překladu realizovat buď pomocí dědičnosti (klíčové slovo extends) nebo pomocí interfaců (implements). Dědění používáme, pokud potřebujeme nějakým způsobem vytvořit hierarchii objektů a sdílet společný kód mezi členy hierarchie. Interfacy slouží jen k definování, že třída, která interface implementuje, má rozumět těm a těm zprávám (implementovat příslušné metody).
Pozor, rozhodně neplatí, že dědičnost == polymorfismus. Pokus o prosazení této rovnosti pro vás bude pravděpodobně znamenat nedobrovolný odchod ze zkoušky . Dědičnost je jen jeden ze způsobů, jak polymorfismus zařídit v jazyce typu Java.
Kruh.java
Kruh je potomkem třídy Utvar2D. Abychom mohli vytvářet instance, potřebujeme implementovat metody obvod a obsah.
package omo4; public class Kruh extends Utvar2D{ int x, y, r; public Kruh (int x, int y, int r) { this.x = x; this.y = y; this.r = r; } public double obvod(){ return 2 * Math.PI * r; } public double obsah() { return Math.PI * r * r; } }
Obdelnik.java
Obdelnik je potomkem třídy Utvar2D a zároveň implementuje interface Hranaty (hranatý objekt, objekt s hranami) - metoda nejdelsiHrana.
package omo4; public class Obdelnik extends Utvar2D implements Hranaty{ int x1,y1,x2,y2; public Obdelnik (int x1, int y1, int x2, int y2){ this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } public double obvod (){ return (Math.abs(x2 - x1) * 2) + (Math.abs(y2 - y1) * 2); } public double obsah() { return Math.abs(x2 - x1) * Math.abs(y2 - y1); } public double nejdelsiHrana() { return Math.max(Math.abs(x2 - x1), Math.abs(y2 - y1)); } }
Utvar2D.java
Abstraktní třídy, narozdíl od interfaců, mohou mít i metody s definovaným kódem a tak definovat nějaké metody společné pro všechny podtypy. Naši hierarchii rozšíříme o jednu úroveň a dodáme nadřazenou třídu (superclass) Utvar (a případně sourozence Utvar3D). Teď můžeme potřebovat metodu jeRovinny, která by pro všechny 2D útvary (čili potomky Utvar2D) vracela true. Pak se jeví vhodné ji vložit přímo do třídy Utvar2D.
package omo4; public abstract class Utvar2D extends Utvar{ public boolean jeRovinny(){ return true; } public abstract double obvod(); public abstract double obsah(); }
Utvar.java
Třída pro všechny útvary. Dal jsem ji sem jen kvůli příkladu na metodu v abstraktní třídě.
package omo4; public abstract class Utvar { public abstract boolean jeRovinny(); }
Hranaty.java
Interface pro všechny útvary s hranami. U nich chceme určovat i délku nejdelší hrany.
package omo4; public interface Hranaty { public double nejdelsiHrana(); }
Main.java
package omo4; public class Main { public static double sectiObvody(Utvar2D[] pole){ double soucet = 0; for (Utvar2D prvek: pole){ soucet += prvek.obvod(); } return soucet; } public static double vratMaxHranu(Hranaty[] pole){ double max = 0; for (Hranaty prvek: pole){ if (prvek.nejdelsiHrana() > max){ max = prvek.nejdelsiHrana(); } } return max; } public static void main (String [] args){ Kruh k = new Kruh (0,0,10); System.out.println(k.obvod()); Obdelnik o = new Obdelnik(0, 0, 10, 20); System.out.println(o.obvod()); System.out.println(o.jeRovinny()); Utvar2D [] pole = new Utvar2D[2]; pole[0] = k; pole[1] = o; System.out.println(sectiObvody(pole)); Hranaty[] pole2 = new Hranaty[2]; pole2[0] = o; pole2[1] = new Obdelnik(0,0,14,15); System.out.println(vratMaxHranu(pole2)); } }