2. seminář - Objektově orientované programování

TEACHINGJJ1

Motivace

V tomto kurzu se budeme zabývat Objektově oritentovaným programováním (OOP) pouze intuitivně. Přesněji a podrobněji se OOP věnuje kurz Paradigmata programování 3.

Jako motivační příklad si vezměme například system vozidlo v zavodní hře. Všechna vozidla sdílí některé vlastnosti jako je počet kol, volant, apod. Liší se například výkonem motoru, barvou karoserie. Těmto vlastnostem budeme říkat atributy.

Kromě atributů mohou vozidla vykonávat různé akce jako zrychlit, zpomalit, zabrzdit, atd.

Výše uvedené požadavky lze splnit i pomocí procedurálního programování. Lepším řešením je ale použít tzv Objekty. Objekt je část programu, která sdružuje vlastnosti nějaké entity (v našem případě auta) a umožňuje s touto entitou provádět akce (zrychlit, zpomalit). Akce budeme nazývat metody.

OOP v Javě

Pokud chceme pracovat s objekty, tak jako první musíme vyrvořit šablonu, která nám řekne jake vlastnosti daný objekt má a jaké může provádět akce. Šablonu nazýváme třída a definujeme ji následovně:


    class Car {
        /**
         *  Vyrobce vozidla
         */
        String manufacturer;

        /**
         *  Statni poznavaci znacka
         */
        String licensePlateNumber;

        /**
         *  Barva vozidla
         */
        String color;

        /**
         *  Aktualni rychlost
         */
        int speed = 0;

        /**
         *  Vykon motoru. Atribut neni mozne menit.
         */
        final int power;

        /**
         *  Konstruktor
         */
        Car(String manufacturer, String licensePlateNumber, String color, int speed, int power) {
            this.manufacturer = manufacturer;
            this.licensePlateNumber = licensePlateNumber;
            this.color = color;
            this.speed = speed;
            this.power = power;
        }

        /**
         *  Metoda pro zmenu barvy
         */
        void changeColor(String color) {
            this.color = color;
        }

        /**
         *  Zrychleni
         */
        boolean speedUp(int speed){
            this.speed += speed;
            return true;
        }

        /**
         *  Zpomaleni
         */
        boolean slowDown(int speed) {
            this.speed -= speed;
            return true;
        }
        
        /**
        *   Metoda pro prevod objektu na retezec
        */
        @Override
        public String toString() {
            return manufacturer + " " + licensePlateNumber;
        }
    }

Práce s objekty

Před tím, než začneme pracovat s objektem v Javě (i v jiných jazycích), musíme jej nejdříve vytvořit. To se v Javě děla pomocí klíčového slova new. Takto vytvořenému objektu říkáme instance třídy.


    // Vytvoreni instance
    Car fordFocus = new Car("Ford",
            "1M1 1234",
            "Red",
            134);

    // Pristup k atributum (jen pro 2. seminar!!!)
    System.out.println(fordFocus.licensePlateNumber);

    // Volani metody
    fordFocus.changeColor("Yellow");

    boolean speedUp = fordFocus.speedUp(20);

Řetezce

Ve výše uvedeném příkladu se vyskytl datový typ String. Jedná se o třídu reprezentující řetezce. Třída nabízí celou škálu metod pro práci řetezci. Více se lze dočíst v dokumentaci. Pozor String není to samé jako char[]!

Pro převod objektu na textový řetezec se používa metoda toString(), kterou je potřeba nejdříve implementovat.

Příklad práce s řetezci


    // Vytvoreni retezce
    String name = "Johny English";
    
    // Textovy blok
    String longText = """
        Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
        Nullam feugiat, turpis at pulvinar vulputate, 
        erat libero tristique tellus, nec bibendum odio risus 
        sit amet ante. Etiam sapien elit, consequat eget, 
        tristique non, venenatis quis, ante. Mauris metus.""";
        
    // Vytvoreni retezce z pole znaku
    char[] greetingArray = { 'h', 'e', 'l', 'l', 'o', '.' };
    String greetingString = new String(greetingArray);
    
    // Vypis na obrazovku
    System.out.println(longText);
    
    // Delka retezce
    int length = greetingString.length();

    // Ziskani znaku na indexu 2
    char letter = longText.charAt(2);

Spojování řetězců

U řetězců v Javě nelze měnit hodnoty. Pokud chceme do řetezce přidat nějaký znak, tak musíme vytvořit nový. To je ale značne neefektivní proto exituje třída StringBuilder která tento neduh odstraňuje.

Spojování pomocí concat a +


    String firstName = "Luke";
    String lastName = "Skywalker";
    String fullName;

    // Metoda concat spoji 2 retezce a vytvori novy
    fullName = firstName.concat(lastName);

    // Metoda lze zavolat i na literaly
    fullName = "Luke".concat("Skywalker");

    // Lze pouzit i operaci +
    fullName = "Luke" + lastName;

Třída StringBuilder

Níže jsou uvedeny nejčastěji používané metody. Pro kompletní výčet odkazuji na dokumentaci.


    // Vytvoreni StringBuilder
    StringBuilder stringBuilder = new StringBuilder();
    StringBuilder stringBuilderWithCapacity = new StringBuilder(30);
    StringBuilder stringBuilderWithString = new StringBuilder("Hello");

    // Delka
    int length = stringBuilderWithString.length();

    // Pripojeni retezce na konec
    stringBuilderWithString.append("Luke Skywalker.");

    // Vlozeni retezce na dany index
    stringBuilderWithString.insert(5, ", I am jedi master ");

    // Nahrazeni casti retezce
    stringBuilderWithString.replace(12, 23, "Jedi Master");

    // Vymazani casti retezce
    stringBuilderWithString.delete(12, 24);

    // Znak na danem indexu
    char letter = stringBuilderWithString.charAt(2);

    // Podretezec
    String substringFrom = stringBuilderWithString.substring(12);
    String substringFromTo = stringBuilderWithString.substring(12, 16);

Pole

Stejně jako jazyk C i jazyk Java umožňuje vytvářet pole hodnot.

Vytvoření pole


    // Deklarace pole
    String[] cars;
    
    // Deklarace pole s hodnotami
    String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
    
    // Vytvoreni "prazdneho" pole pro 10 prvku
    int[] numbers = new int[10];

Přístup k prvkům pole

Práce s poli se neliší o jazyka C.


    // Pristup k prvku
    System.out.println(cars[0]);
    
    // Nastaveni prvku pole
    cars[1] = "Škoda";

Délka pole

Jazyk Java poskytuje atribut length který nám vrátí délku pole.


    // Vypis delky pole
    System.out.println(cars.length);

Iterace přes prvky pole


    // Iterace pres indexy
    for (int i = 0; i < cars.length; i++) {
        System.out.println(cars[i]);
    }

    // Iterace pres prvky
    for (String car : cars) {
        System.out.println(car);
    }

Třída Arrays

V Javě máme k dispozici třídu Arrays. Ve které jsou implementovány nejčastěji používané oprace s poli. Níže je malá ukázka (podrobněji viz dokumentace).


    String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
    
    // Vyhleda dany prvek v poli a vrati jeho index.
    // V pripade neuspechu vraci zapornou hodnotu.
    Arrays.binarySearch(cars, "Mazda");

    // Prevede pole na retezec
    Arrays.toString(cars);

    // Setridi pole
    Arrays.sort(cars);

    // Porovna lexikograficky dve pole a vraci hodnotu:
    //            0 - Pokud jsou stejna
    //  mensi nez 0 - Pokud je prvni pole mensi (lexikograficky) nez druhe
    //  vetsi nez 0 - V ostatnich pripadech
    Arrays.compare(cars, new String[] {"Mazda", "BMW"});

Úkoly

Úkoly mi neposílejte, budou zkontrolovány na dalším semináři.

Vytvořte třídu Country s konstruktorem Country(String name, String phoneCode), která reprezentuje stát. Objekty mají dva atributy - name (jméno státu) a phoneCode (telefonní předvolba, např. +420). Dále definujte metodu print, která vypíše zemi ve formátu Stát{jméno=xxx, předvolba=xxx} a ukončí řádek.
Vytvořte třídu Person s konstruktorem Person(int id, String firstname, String lastname, int age, String phone, Country country), která reprezentuje osobu. Objekty mají atributy: id (unikátní identifikátor), firstname (jméno), lastname (příjmení), age (věk), phone (telefon), country (stát). Dále definujte metodu getStatus(), která vrátí status osoby: pokud je věk menší než 18, vrátí status “junior”, pokud větší nebo roven 65, vrátí status “senior”, jinak vrátí status “dospělý”.
Třídě Person definujte metodu getPhone(), která vrátí telefonní číslo i s předvolbou. Pokud osoba nemá stát přiřazený, vrátí číslo bez předvolby.
Třídě Person definujte metodu print(), která vypíše osobu ve formátu Osoba{id=xxx, jméno=xxx, příjmení=xxx, věk=xxx, telefon=xxx, status=xxx, stát=xxx} a ukončí řádek. Pokud osoba nemá stát přiřazený, vypíše stát=neznámý.
Vytvořte třídu Index s konstruktorem Index(Person[] persons, Country[] countries), která reprezentuje rejstřík. Rejstřík obsahuje pole osob a pole států. Dále definujte metodu count(String countryName), která vrací počet osob, žijících v určitém státě.
Třídě Index definujte metodu count(String firstname, String lastname), která vrátí počet osob se stejným jménem a příjmením.
Třídě Index definujte metodu search(int id), která vyhledá osobu s určitým id.
Třídě Index definujte metodu search(String countryName), která vyhledá všechny osoby žijící ve státě určeném jménem.
Třídě Index definujte metodu search(String firstname, String lastname), která vyhledá všechny osoby se zadaným jménem a příjmením.
Třídě Index definujte metodu setPhoneCode(Person person, String phoneCode), která osobě nastaví zemi podle telefonní předvolby. Pokud je předvolba neplatná, neudělá nic a vrátí hodnotu false (jinak true).

Třídě Index definujte metodu print(), která vypíše (efektivním způsobem!) obsah rejstříku ve formátu:

Rejstřík{ Osoba{id=0, jméno=Prokop, příjmení=Dveře, telefon=+420555444333} Osoba{id=1, jméno=Tomáš, příjmení=Putna, telefon=+420999888777} Osoba{id=2, jméno=Fero, příjmení=Dunaj, telefon=+421123456789} Osoba{id=3, jméno=Johnny, příjmení=Cash, telefon=+1987654321} Osoba{id=4, jméno=Tomáš, příjmení=Putna, telefon=111222333} } a ukončí řádek.