OOPR_06
1
Obsah přednášky • • • • • • •
Refaktorování Návrhové vzory – význam, použití Návrhový vzor přepravka (Messenger) Testování programů testovací třída JUnit Návrhový vzor singleton – jedináček Návrhový vzor – výčtový typ Další možnosti třídy JUnit na testování programů
2
Refaktorování • Refaktorování kódu programu je proces, změny zdrojového kódu, bez modifikace externího funkčního chování za účelem zlepšení některých nefunkčních parametrů software. • Výhody dále zahrnují zlepšení čitelnosti kódu, snížení složitosti, zlepšení udržovatelnosti (maintainability) kódu, zlepšení rozšiřitelnosti.
3
Návrhové vzory – design patterns význam a použití • nejdůležitější zásada produktivního programátora nevynalézat již vynalezené, • OOP podporuje znovupoužitelnost na úrovni kódu – znovupoužití vytvořených tříd, • návrhové vzory – návody na řešení, některých typických, často se opakujících úloh na úrovni mentálních bloků, • 1995 – první kniha Design Patterns – přeložená do češtiny obsahující prvních 23 návrhových vzorů, 4
Návrhové vzory – design patterns význam a použití • stále rostoucí důraz na návrhové vzory, které zlepšují a zpřehledňují programové řešení. • zakladatel vzorů – architekt Christopher Alexander – jeho kniha: A Pattern Language: Towns, Buildings, Constructions – pokoj se dvěma okny – místo s jedním
• ovlivnil také programátorskou komunitu. • Jeho práce ukázaly, že vzory jsou výbornou cestou k pochopení a transportu moudrosti daného řemesla. 5
Návrhové vzory – design patterns • Další literatura: Bruce Eckel: Thinking in Patterns web adresa: www.bruceeckel.com • Základní popis návrhových vzorů: • kontext ve kterém problém vzniká • problém, který je třeba vyřešit • řešení daného problému
6
Vzor Messenger – Přepravka (Posel, kurýr) • Problém: pracovat s několika hodnotami jako hodnotou jednou a umožnit tak snadné přenášení této skupiny hodnot mezi jednotlivými instancemi a jejich metodami (návrat objektu z metody). • Kontext: práce v objektově orientovaném prostředí • Řešení: všechny hodnoty jakoby naskládáme do přepravky (objektu) s danou strukturou a předáme žadateli hodnot. • Přepravky jsou určeny pro předem definovanou sadu hodnot – „každý druh nářadí má připraven vlastní úchyt“.
7
Přepravka & skládání agregace • Řešení návrhového vzoru přepravka se podobá do jisté míry skládání objektů typu agregace. Přepravka je celek, části jsou jednotlivé objekty – atributy. • u částí je však použit modifikátor public (místo private) • pro všechny části jsou vždy uvedeny všechny přístupové a modifikační metody C a s t_ 1
1
C e le k + g e tM e to d a () + s e tM e to d a ()
C a s t_ 2 1 1
1
1
C a s t_ 3 1
8
Vzor Messenger – Přepravka (Posel, kurýr) • Třída, jejíž instance mají sloužit jako přepravky předem známé sady hodnot, by měla mít následující vlastnosti: – pro každou přenášenou hodnotu bude definován vlastní atribut, do kterého se hodnota (objekt) „uloží“, – účelem třídy je přenos a snadná dostupnost k přenášeným atributům, jsou tyto deklarované jako public, veřejné (dodržovat přístupové metody), – datové atributy jsou jednoduché nebo objektové typy.
9
Vzor Messenger – Přepravka (Posel, kurýr) • Kromě metod nastavujících jednotlivé atributy, mají třídy „přepravky“ metody pro kopírování hodnot atributů instance, předávané jako parametr např. setPozice(Pozice) podobně jako tzv. kopírovací konstruktor
10
// prepravka public class Bod { public int x, y, z; public Bod(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } // kopirovaci konstruktor public Bod(Bod p) { this.x = p.x; this.y = p.y; this.z = p.z; } public String toString() { return "x: " + x + " y: " + y + " z: " + z; } }
Poznámky
11
public class Vektor { private int velikost, smer; public Vektor(int velikost, int smer) { this.velikost = velikost; this.smer = smer; } public int getVelikost() { return velikost; } public int getSmer() { return smer; } }
Poznámky
12
public class Plocha { public static Bod translate(Bod p, Vektor v) { p = new Bod(p); // nemodifikuje objekt v parametru // vykonani smyslenych operaci: p.x = p.x + v.getVelikost(); p.y = p.y + v.getSmer(); p.z = p.z + v.getVelikost() * v.getSmer(); return p; } }
Poznámky
public class Prepravka { public static void main(String[] args) { Bod p1 = new Bod(1, 2, 3); Bod p2 = Plocha.translate(p1, new Vektor(11, 47)); String vysledek = "p1: " + p1 + "\np2: " + p2; System.out.println(vysledek); } }
Poznámky
14
Testování programů – knihovna JUnit • Tvorba aplikace – vytvoření knihovních tříd; vytvoření testovací třídy s hlavní metodou, • testovací třída (přípona Test) by měla otestovat vytvořené knihovní třídy. • Moderní programování – preferovaná myšlenka definovat nejprve sadu testů a teprve pak psát testovaný program, • jakmile program projde, programátor přemýšlí, jak by jej měl zlepšit.
15
Testování programů – knihovna JUnit • Napíše testy a snaží se upravit program, aby vyhověl testům. • Cyklus se může několikrát opakovat. • Agilní metody vývoje.
16
Testování programů – knihovna JUnit • Zkušenosti ukazují, že připravená sada testů vede k vyšší efektivnosti při tvorbě programů. • Automatizace testování – knihovna JUnit polovina 90. let. V současné době je jednou z povinných součástí profesionálních vývojových prostředí www.junit.org • je součástí prostředí BlueJ i Eclipse.
17
Zprovoznění JUnit v BlueJ 1. V hlavní nabídce vyberete Tools (Nástroje)> Preferences (Nastavení) 2. Následně v Preferences vyberete záložku Miscellaneous (Různé) 3. Zaškrtnete políčko Show unit testing tools (Zobrazit nástroje pro testování) 4. Stiskem OK své zadání potvrďte
18
Poznámky Run Tests – spustit testy recording – záznam End – Ukončit Cancel – Storno
19
Testovací třída • V nabídce new class (nová třída) můžeme zadat, že chceme vytvořit Unit Test třídu (jedná se o test jednotky) • <
> je tzv. stereotyp, který se používá v jazyce UML, v případě specifikace nějaké speciální vlastnosti (na první pohled odlišíme testovací třídu od ostatních tříd)
20
Poznámky Vytvoření testovacích tříd
21
Knihovna JUnit a metody assertEquals a assertTrue • tzv. potvrzovací metody (série potvrzovacích metod), • pomocí potvrzovacích metod ověříme, zda je vše během testování v pořádku, • assertEquals(t, o, s) resp. assertEquals(t, o, s, r) – parametr t je text, který se vytiskne v případě, že náš předpoklad nebude potvrzen. Tento parametr není povinný (existují přetížené metody, které ho nemají). 22
Knihovna JUnit a metody assertEquals a assertTrue – parametr o je očekávaná hodnota – parametr s je spočtená hodnota, o které předpokládáme, že bude rovna očekávané hodnotě – parametr r se použije pouze při porovnávání reálných čísel. Je v něm uložen rozdíl, o který se dvě reálná čísla mohou lišit, abychom jej pokládali za shodná.
23
Knihovna JUnit a metody assertEquals a assertTrue • Pokud se očekávaná hodnota a spočtená hodnota liší, metoda vypíše v testovacím okně zadaný text, očekávanou a obdrženou hodnotu a daný test ukončí. • Metoda assertTrue(boolean) zestručnělá verze assertTrue(boolean, boolean), které předáváme jako první parametr očekávanou hodnotu a druhá je obdržená hodnota.
24
Napsání testu pomocí knihovny JUnit • Učinit danou třídu podtřídou třídy JUnit.framework.TestCase - klíčové slovo extends • Testovací třída obsahuje připravený konstruktor a dvě prázdné metody: setUp() a tearDown().
25
Napsání testu pomocí knihovny JUnit • Kód potřebný pro definici přípravku se vloží do metody setUp() – tělo metody setUp() je většinou naplněno vytváření potřebných objektů a přiřazení odkazů na tyto objekty – při dalším použití je lépe restartovat JVM
• Metoda tearDown() slouží pro úklid po testování (odstranění nepotřebných objektů).
26
public class TestTestu extends junit.framework.TestCase { private int i1; private String s1; private Bod b1;
Poznámky
//Priprava a uklid pripravku /*********************************************************************** * Vytvoreni pripravku (fixture), tj. sady objektu, s nimiz budou vsechny * testy pracovat a ktera se proto vytvori pred spustenim kazdeho testu. */ protected void setUp() { System.out.println( "\n=== Priprava testu " + getName() ); i1 = 1; s1 = "Jedna"; b1 = new Bod(); } /******************************************************************* * Uklid po testu - tato metoda se spusti po vykonani kazdeho testu. */ protected void tearDown() { b1 = null; //pouziti metod napr. pro mazani System.out.println( "XXX Uklizeno po testu " + getName() ); }
27
//== VLASTNI TESTY =============================================================
Poznámky
public void testCisel() { System.out.println( "Cisla souhlasi" ); assertEquals( "Neshoda celeho cisla", 1, i1 ); System.out.println( "Cisla nesouhlasi" ); assertEquals( "Neshoda celeho cisla", 0, i1 ); //chyba System.out.println( "Konec testu cisel" ); } public void testSouradnic() { System.out.println( "Souradnice souhlasi" ); assertEquals( "Neshoda souradnic", 0, b1.getX() ); System.out.println( "Souradnice nesouhlasi" ); assertEquals( "Objekty se lisi", null, b1 ); //chyba assertEquals( "Neshoda souradnic", 1, b1.getY() ); //chyba System.out.println( "Konec testu souradnic" ); } public void testRetezcu() { System.out.println( "Retezce souhlasi" ); assertEquals( "Neshoda textu", "Jedna", s1 ); System.out.println( "Retezce souhlasi" ); assertEquals( "Neshoda textu", "Dva", s1 ); //chyba System.out.println( "Konec testu retezcu" ); } }
28
TestRunners – testovací spouštěče • V JUnit jsou zabudované tři TestRunnery • JUnit.awtui.TestRunner – zobrazení výsledků (views) používá grafické řízení, které má úzkou vazbu na daný operační systém (nativní) • JUnit.swingui.TestRunner - na zobrazení výsledků se používá grafické řízení implementované Java Swing • JUnit.textui.TestRunner – zobrazení výsledků probíhá v textové formě 29
import junit.framework.*;
Poznámky
class Point { //prepravka public int x, y, z; //prepravni atributy public Point(int x, int y, int z){ this.x = x; this.y = y; this.z = z; } public Point(Point p){// kopirovaci konstruktor this.x = p.x; this.y = p.y; this.z = p.z; } public String toString(){ return "x: "+x+" y: "+ y+" z: "+z; } public void print(){ System.out.println(this.toString()); } }
30
class Vector{ public int magnitude; int direction; public Vector(int magnitude, int direction){ this.magnitude = magnitude; this.direction = direction; } public String toString(){ return "Vector magnitude: "+magnitude+" direction: "+direction; } public void print(){ System.out.println(this.toString()); } }
Poznámky
class Space{ public static Point translate(Point p, Vector v){ p = new Point(p);//nova instance pres kopirovaci konstruktor // nemodifikuje original p.x = p.x + 1; p.y = p.y + v.magnitude; p.z = p.z + v.direction; return p; } }
31
public class PrepravkaJUnit extends TestCase { public void test(){ Point p1 = new Point(1, 2, 3); Point p2 = Space.translate(p1, new Vector(11, 32)); String result = "p1: "+ p1 +" p2: "+ p2; p1.print(); p2.print(); System.out.println(result); assertEquals(result, "p1: x: 1 y: 2 z: 3 p2: x: 2 y: 13 z: 35"); } public static void main(String[] args){ junit.textui.TestRunner.run(PrepravkaJUnit.class);
Poznámky
} }
32
Jedináček - Singleton • Problém: • definovat třídy tak, aby uživatel nemohl svobodně ovlivňovat počet jejich instancí – chceme např. aby se vytvořila pouze jedna instance dané třídy
• Kontext: • v mnoha aplikacích potřebujeme, aby vznikla pouze jedna instance (objekt) sdílený celou aplikací
33
Jedináček - Singleton • Řešení: • definovat konstruktor jako soukromý – private tím je zabezpečeno, že se ke konstruktoru dostaneme pouze prostřednictvím jiné metody, která bude veřejná, • použít při deklaraci takové třídy modifikátor final, který zabezpečí, že třída již nemůže mít potomky (nedovolí deklaraci dalších podtříd),
34
Jedináček - Singleton • Přímo v deklaraci třídy se vytvoří nová instance (objekt) s daným označením, které je přístupné např. prostřednictvím metody getReference(). • Metoda pro získání odkazu na jediný objekt, jedináček se deklaruje jako statická, což umožňuje vytvářet instance s využitím názvu třídy.
35
final class Singleton { private int i; private static Singleton s = new Singleton(47); private Singleton(int x) { i = x; //konstruktor s jednim argumentem }
Poznámky
public static Singleton getReference() { return s; //ziskani reference } public int getValue() { return i; } public void setValue(int x) { i = x; } public String toString(){ return "Singleton i: "+this.getValue(); } public void tisk(){ System.out.println(this.toString()); } }
36
public class SingletonTest { public void test() { Singleton s = Singleton.getReference(); //vytvoreni nove instance
Poznámky
String result = "" + s.getValue(); System.out.println(result); Singleton s2 = Singleton.getReference(); s2.setValue(9); result = "" + s.getValue(); System.out.println(result); s.tisk(); s2.tisk(); if(s == s2)System.out.println("Rovnaji se"); else System.out.println("Nerovnaji se"); } public static void main(String[] args) { new SingletonTest().test(); } }
37
import junit.framework.*; // // // //
Since this isn't inherited from a Cloneable base class and cloneability isn't added, making it final prevents cloneability from being added through inheritance:
Poznámky Vzor Singleton a knihovna JUnit
final class Singleton { private static Singleton s = new Singleton(47); private int i; private Singleton(int x) { i = x; } public static Singleton getReference() { return s; } public int getValue() { return i; } public void setValue(int x) { i = x; } }
38
public class SingletonPattern extends TestCase { public void test() { Singleton s = Singleton.getReference(); String result = "" + s.getValue(); System.out.println(result); assertEquals(result, "47"); Singleton s2 = Singleton.getReference(); s2.setValue(9); result = "" + s.getValue(); System.out.println(result); assertEquals(result, "9");
Poznámky Vzor Singleton a knihovna JUnit
try { // Can't do this: compile-time error. // Singleton s3 = (Singleton)s2.clone(); } catch(Exception e) { throw new RuntimeException(e); } } public static void main(String[] args) { junit.textui.TestRunner.run(SingletonPattern.class); } }
39
public class Ucet { private int cislo; private double stav; private static Ucet ucetSingleton;
Poznámky Třída Účet jako singleton
// konstruktory private Ucet(int cislo, double stav) { this.cislo = cislo; this.stav = stav; } private Ucet() { this(100, 0.0); } private Ucet(int cislo) { this(cislo, 0.0); } private Ucet(double castka) { this(0, castka); } // tovarni metoda pro ziskani instance uctu public static Ucet getInstance() { if(ucetSingleton == null) ucetSingleton = new Ucet(1, new Koruny(0.0)); return ucetSingleton; }
40
public class Osoba { private String jmeno; private int rokNarozeni; private static Ucet ucet = Ucet.getInstance();
public void vlozeni(double castka) { ucet.vlozeni(castka); } public double vyber(double castka) { return ucet.vyber(castka); }
Poznámky Třída Účet jako singleton Použití „globálního“ odkazu
41
public class OsobaX { private String jmeno; private int rokNarozeni; //private static Ucet ucet = Ucet.getInstance(); public String toString() { Ucet ucet = Ucet. getInstance(); return String.format("%s %s %s %d\n%s", "Jmeno: ", getJmeno(), "vek: ", getVek(), ucet.toString()); } public void tisk() { System.out.println(toString()); } public void vlozeni(Koruny koruny) { Ucet ucet = Ucet.getInstance(); ucet.vlozeni(koruny); } public void vyber(Koruny koruny) { Ucet ucet = Ucet.getInstance(); ucet.vyber(koruny); }
Poznámky Třída Účet jako singleton Použití lokálních odlazů
42
Výčtové typy •
• • •
Problém: Definovat předem daný (známý) počet instancí, jež se zveřejní jako statické (třídní) atributy třídy. Tyto třídy představují většinou neměnné hodnotové typy. Kontext: implementace konkrétních problémů. Předem stanovený počet objektů (instancí), které se chovají jako konstanty 43
Výčtové typy • Řešení: Výčtové typy – mají předdeklarované některé atributy a metody viz přednáška OOP_4 • Pravidla: 1.V těle třídy musíme nejprve deklarovat seznam jeho hodnot, všechny ostatní atributy a metody musíme deklarovat až za vím. 2.V nejjednodušším případě se jedná pouze o seznam názvů oddělených čárkami
44
Složitější definice výčtových typů • výčtový typ může mít své podtypy, • to znamená, že může obsahovat ještě další data, • např. výčtový typ Barva může obsahovat celočíselný identifikátor id, textový výraz a cenu jako double, • kromě tohoto popisu, musí mít výčtový typ soukromý konstruktor, soukromé neměnné datové atributy (final) • přístupové metody k podtypům. 45
public enum Barva {ZELENA(23, "green", 128.50 ), CERVENA(19, "red", 38.60), ZLUTA(68, "yellow", 148.70), SVETLE_CERVENA(41,"light-red", 87.30);
Poznámky
private final int id; private final String jmeno; private final double cena; Barva(int c, String s, double d){ id = c; jmeno = s; cena = d; } public int getId(){ return id; } public String getJmeno(){ return jmeno; } public double getCena(){ return cena; }
// nesmi byt public
}
46
public class BarvaTest {
Poznámky
public static void main(String[] args) { System.out.println("Tisk vsech hodnot"); for (Barva bv : Barva.values()) System.out.printf("\nid: %d text: %s cena: %.2f", bv.getId(), bv.getJmeno(), bv.getCena()); Barva b = Barva.ZLUTA; System.out.println("cena zluta: "+b.getCena());
} }
47
import javax.swing.JOptionPane; public class JablkoTest {
Poznámky
public static void main(String[] args) { Jablko j = new Jablko(); j.tisk(); Jablko j1 = new Jablko(Barva.valueOf("ZELENA"), 12, Chut.valueOf("VYBORNA")); Chut c; j1.tisk(); Jablko j2 = new Jablko(Barva.SVETLE_CERVENA, 15, Chut.ODPORNA); j2.tisk(); int k = j2.getChut().ordinal(); System.out.println("Poradi chuti: "+k); String t = j2.getChut().name(); System.out.println("Chut objektu j2 textove: "+t); c = j.getChut(); System.out.printf("Objekt j chut poradi: %d textove: %s", c.ordinal(), c.name()); String nazev = JOptionPane.showInputDialog("Zadejte barvu jablka:"); nazev = nazev.toUpperCase(); Barva b = Barva.valueOf(nazev); System.out.printf("\nZadana barva: %s poradi: %d", b.name(),b.ordinal()); double d = j1.getBarva().getCena(); String s = j2.getBarva().getJmeno(); } }
48
public enum Book { // declare constants of enum type JHTP6( "Java How to Program 6e", "2005" ), CHTP4( "C How to Program 4e", "2004" ), IW3HTP3( "Internet & World Wide Web How to Program 3e", "2004" ), CPPHTP4( "C++ How to Program 4e", "2003" ), VBHTP2( "Visual Basic .NET How to Program 2e", "2002" ), CSHARPHTP( "C# How to Program", "2002" );
Poznámky Další příklad s výčtovým typem kniha
// instance fields private final String title; // book title private final String copyrightYear; // copyright year // enum constructor Book( String bookTitle, String year ) { title = bookTitle; copyrightYear = year; } // end enum Book constructor
49
// accessor for field title public String getTitle() { return title; } // end method getTitle
Poznámky
// accessor for field copyrightYear public String getCopyrightYear() { return copyrightYear; } // end method getCopyrightYear } // end enum Book
50
public class EnumTest { public static void main( String args[] ) { System.out.println( "All books:\n" );
Poznámky
// print all books in enum Book for ( Book book : Book.values() ) System.out.printf( "%-10s%-45s%s\n", book, book.getTitle(), book.getCopyrightYear() ); System.out.println( "\nDisplay a range of enum constants:\n" ); // print first four books for ( Book book : EnumSet.range( Book.JHTP6, Book.CPPHTP4 ) ) System.out.printf( "%-10s%-45s%s\n", book, book.getTitle(), book.getCopyrightYear() ); } // end main } // end class EnumTest
51
Poznámky
All books: JHTP6 CHTP4 IW3HTP3 CPPHTP4 VBHTP2 CSHARPHTP
Java How to Program 6e C How to Program 4e Internet & World Wide Web How to Program 3e C++ How to Program 4e Visual Basic .NET How to Program 2e C# How to Program
2005 2004 2004 2003 2002 2002
Display a range of enum constants: JHTP6 CHTP4 IW3HTP3 CPPHTP4
Java How to Program 6e C How to Program 4e Internet & World Wide Web How to Program 3e C++ How to Program 4e
2005 2004 2004 2003
52
Metody knihovny JUnit aplikované na třídě Zlomek • statická třída Funkce – obsahuje další třídní metody dostupné bez vytvoření instance od třídy Funkce • základní třída Zlomek • metoda ZlomekTest
53
/************************************************************************* * Trida Funkce obsahuje pomocne staticke metody pro tridu Zlomek. Resi * vypocet nejmensiho spolecneho nasobku a nejvetsiho spolecneho delitele. * @author Rudolf Pecinovsky * @version 0.00.000, 30. brezen 2004, 23:17 */ public final class Funkce {
Poznámky Funkce 1/2
/*********************************************************************** * Vrati nejvetsiho spolecneho delitele dvou zadanych cisel. * Vracene cislo je vzdy kladne nezavisle na znamenku parametru. * * @param i1 Prvni cislo * @param i2 Druhe cislo * * @return Nejvetsi spolecny delitel zadanych cisel */ public static int nsd(int i1, int i2) { i1 = Math.abs( i1 ); i2 = Math.abs( i2 ); while( i2 > 0 ) { int pom = i1 % i2; i1 = i2; i2 = pom; } return i1; }
54
/*********************************************************************** * Vrati nejmensi spolecny nasobek zadanych cisel. * Vracene cislo je vzdy kladne nezavisle na znamenku parametru. * * @param i1 Prvni cislo * @param i2 Druhe cislo * * @return Nejmensi spolecny nasobek zadanych cisel */ public static int nsn(int i1, int i2) { if( (i1 == 0) || (i2 == 0) ) return 0; return i2 * Math.abs(i1) / nsd(i1,i2); }
Poznámky Funkce 2/2
//######################################################################## //== KONSTRUKTORY A TOVARNI METODY ============================================= private Funkce() {}
}
55
public class Zlomek_4 { private final int citatel; private final int jmenovatel;
Poznámky Třída Zlomek
public Zlomek_4(int c, int j) { //při vytvoreni noveho objektu se provede uprava int delitel = Funkce.nsd( c, j ); if( j < 0 ) { c = -c; j = -j; } citatel = c / delitel; jmenovatel = j / delitel; }
public Zlomek_4(Zlomek_4 z) //kopirovaci konstruktor { citatel = z.citatel; jmenovatel = z.jmenovatel; }
public Zlomek_4(int cislo) { citatel = cislo; jmenovatel = 1; }
56
//== PRISTUPOVE METODY VLASTNOSTI INSTANCI =====================================
Poznámky
public int getCitatel() { return citatel; } public int getJmenovatel() { return jmenovatel; } public String toString() { return "[" + citatel + "/" + jmenovatel + "]"; }
public int intValue() { return citatel / jmenovatel; } public double doubleValue() { return (double)citatel / jmenovatel; }
57
public Zlomek_4 plus(Zlomek_4 z) { //int nasobek = Funkce.nsn( this.jmenovatel, z.jmenovatel ); return new Zlomek_4( citatel*z.jmenovatel + z.citatel*jmenovatel, jmenovatel*z.jmenovatel ); }
Poznámky
public Zlomek_4 plus(int cislo) { return new Zlomek_4( citatel + cislo*jmenovatel, jmenovatel ); } public Zlomek_4 minus(Zlomek_4 z) { //int nasobek = Funkce.nsn( this.jmenovatel, z.jmenovatel ); return new Zlomek_4( citatel*z.jmenovatel - z.citatel*jmenovatel, jmenovatel*z.jmenovatel ); } public Zlomek_4 minus(int cislo) { return new Zlomek_4( citatel - cislo*jmenovatel, jmenovatel ); } public Zlomek_4 odectiOd(int cislo) { return new Zlomek_4( cislo*jmenovatel - citatel, jmenovatel ); }
58
public Zlomek_4 krat(Zlomek_4 z) { return new Zlomek_4( citatel * z.citatel, jmenovatel * z.jmenovatel ); } public Zlomek_4 krat(int cislo) { return new Zlomek_4( citatel * cislo, }
jmenovatel );
public Zlomek_4 deleno(Zlomek_4 z) { return new Zlomek_4( citatel * z.jmenovatel, z.citatel ); } public Zlomek_4 deleno(int cislo) { return new Zlomek_4( citatel, }
Poznámky
jmenovatel *
jmenovatel * cislo );
public Zlomek_4 delCislo(int cislo) { return new Zlomek_4( jmenovatel * cislo, }
citatel );
}
59
public class Zlomek_4Test extends junit.framework.TestCase { Zlomek_4 z0, z1, z2, z12, z34, z56; Zlomek_4 v1, v2, v3;
Poznámky ZlomekTest
//== PRIPRAVA A UKLID PRIPRAVKU ================================================ /********************************************************************** * Vytvoreni pripravku (fixture), tj. sady objektu, s nimiz budou vsechny * testy pracovat a ktera se proto vytvori pred spustenim kazdeho testu. */ protected void setUp() { System.out.println( "\n" + getName() ); z0 = new Zlomek_4( 0 ); z1 = new Zlomek_4( 1 ); z2 = new Zlomek_4( 2 ); z12 = new Zlomek_4( 1, 2 ); z34 = new Zlomek_4( 3, 4 ); z56 = new Zlomek_4( 5, 6 ); } /********************************************************************* * Uklid po testu - tato metoda se spusti po vykonani kazdeho testu. */ protected void tearDown() { }
60
public static void tiskni( Zlomek_4 v, Zlomek_4 z1, char op, Zlomek_4 z2 ) { System.out.println( v + " = " + z1 + ' ' + op + ' ' + z2 ); }
Poznámky
/************************************************************************* * Pomocna metoda tisknouci zadanou operaci na standardni vystup. * * @param cislo Vysledek prevedeny na retezec * @param z Prevadeny zlomek */ public static void tiskni( String cislo, Zlomek_4 z ) { System.out.println( cislo + " = " + z ); }
61
/*************************************************************************** * Testuje konstruktory a prevod zlomku na retezec. */ public void testToString() { z1 = new Zlomek_4( 2 ); System.out.println("Zlomek_4(2) = " + z1); assertEquals( "[2/1]", z1.toString() );
Poznámky
z1 = new Zlomek_4( 1, 2 ); System.out.println("Zlomek_4(1, 2) = " + z1); assertEquals( "[1/2]", z1.toString() ); z1 = new Zlomek_4( 2, 4 ); System.out.println("Zlomek_4(2, 4) = " + z1); assertEquals( "[1/2]", z1.toString() ); z2 = new Zlomek_4( z1 ); System.out.println("Zlomek_4(" + z1 + ") = " + z2); assertEquals(z1.getCitatel(), z2.getCitatel()); assertEquals(z1.getJmenovatel(), z2.getJmenovatel()); }
62
/*************************************************************************** * Testuje scitani zlomku a zlomku a cisla. */ public void testPlus() { v1 = z1.plus( z2 ); tiskni( v1, z1, '+', z2 ); assertEquals( "[3/1]", v1.toString() );
Poznámky
v2 = z12.plus( z34 ); tiskni( v2, z12, '+', z34 ); assertEquals( "[5/4]", v2.toString() ); v2 = z34.plus( z12 ); tiskni( v2, z34, '+', z12 ); assertEquals( "[5/4]", v2.toString() ); v3 = v1.plus(v2); tiskni( v3, v1, '+', v2 ); assertEquals( "[17/4]", v3.toString() ); v3 = v2.plus(v2); tiskni( v3, v2, '+', v2 ); assertEquals( "[5/2]", v3.toString() ); v3 = v2.plus(2); tiskni( v3, v2, '+', new Zlomek_4(2) ); assertEquals( "[13/4]", v3.toString() ); }
63
// Testuje odcitani zlomku a zlomku a cisla. public void testMinus() { v1 = z1.minus( z2 ); tiskni( v1, z1, '-', z2 ); assertEquals( "[-1/1]", v1.toString() );
Poznámky
v2 = z12.minus( z34 ); tiskni( v2, z12, '-', z34 ); assertEquals( "[-1/4]", v2.toString() ); v2 = z34.minus( z12 ); tiskni( v2, z34, '-', z12 ); assertEquals( "[1/4]", v2.toString() ); v3 = v1.minus(v2); tiskni( v3, v1, '-', v2 ); assertEquals( "[-5/4]", v3.toString() ); v3 = v2.minus(v2); tiskni( v3, v2, '-', v2 ); assertEquals( "[0/1]", v3.toString() ); v3 = v2.minus(2); tiskni( v3, v2, '-', new Zlomek_4(2) ); assertEquals( "[-7/4]", v3.toString() ); v3 = v2.odectiOd(2); tiskni( v3, new Zlomek_4(2), '-', v2 ); assertEquals( "[7/4]", v3.toString() ); }
64
/*************************************************************************** * Testuje nasobeni zlomku a zlomku a cisla. */ public void testKrat() { v1 = z1.krat( z2 ); tiskni( v1, z1, '*', z2 ); assertEquals( "[2/1]", v1.toString() );
Poznámky
v2 = z12.krat( z34 ); tiskni( v2, z12, '*', z34 ); assertEquals( "[3/8]", v2.toString() ); v2 = z34.krat( z12 ); tiskni( v2, z34, '*', z12 ); assertEquals( "[3/8]", v2.toString() ); v3 = v1.krat(v2); tiskni( v3, v1, '*', v2 ); assertEquals( "[3/4]", v3.toString() ); v3 = v2.krat(v2); tiskni( v3, v2, '*', v2 ); assertEquals( "[9/64]", v3.toString() ); v3 = v2.krat(2); tiskni( v3, v2, '*', new Zlomek_4(2) ); assertEquals( "[3/4]", v3.toString() ); }
65
// Testuje deleni zlomku a zlomku a cisla. public void testDeleno() { v1 = z1.deleno( z2 ); tiskni( v1, z1, ':', z2 ); assertEquals( "[1/2]", v1.toString() );
Poznámky
v2 = z12.deleno( z34 ); tiskni( v2, z12, ':', z34 ); assertEquals( "[2/3]", v2.toString() ); v2 = z34.deleno( z12 ); tiskni( v2, z34, ':', z12 ); assertEquals( "[3/2]", v2.toString() ); v3 = v1.deleno(v2); tiskni( v3, v1, ':', v2 ); assertEquals( "[1/3]", v3.toString() ); v3 = v2.deleno(v2); tiskni( v3, v2, ':', v2 ); assertEquals( "[1/1]", v3.toString() ); v3 = v2.deleno(2); tiskni( v3, v2, ':', new Zlomek_4(2) ); assertEquals( "[3/4]", v3.toString() ); v3 = v2.delCislo(2); tiskni( v3, new Zlomek_4(2), ':', v2 ); assertEquals( "[4/3]", v3.toString() ); }
66
// Test prevodu zlomku na cislo public void testPrevody() { int i; double d; Zlomek_4 z125 = new Zlomek_4( 12, 5 );
Poznámky
i = z1.intValue(); tiskni( ""+i, z1 ); assertEquals( 1, i ); i = z34.intValue(); tiskni( ""+i, z34 ); assertEquals( 0, i ); i = z125.intValue(); tiskni( ""+i, z125 ); assertEquals( 2, i, 0 ); d = z1.doubleValue(); tiskni( ""+d, z1 ); assertEquals( 1.0, d, 0 ); d = z12.doubleValue(); tiskni( ""+d, z34 ); assertEquals( 0.5, d, 0 ); d = z125.doubleValue(); tiskni( ""+d, z125 ); assertEquals( 2.4, d, 0 ); }
}
67