You are not allowed to perform this action

Table of Contents

OMO - 3. cvičení - Dědičnost, skládání

Na třídách Stack a SmartStack by měla být vidět výhoda dědičnosti. Stačilo nám překrýt jen metodu push, resp. přidat ještě privátní metodu na zvětšení vnitřního pole, a máme lepší zásobník. Ostatní metody můžeme nechat beze změny a zásobník bude fungovat.

Stack.java

package stack;
 
import java.util.EmptyStackException;
 
public class Stack {
 
    /*
     * Toto byl nebezpecny napad.
     * Proc?
     * protected int capacity;
     * Tady to neni tak vyrazne, ale v druhem priklade uz bude
     */
 
    /*
     * Pole na ukladani hodnot
     */
    protected int [] storage;
 
    /*
     * Index prvniho volneho prvku pole
     */
    protected int index;
 
    /**
     * Konstruktor
     * @param cap kapacita zasobniku
     */
    public Stack(int cap){
        storage = new int [cap];
        index = 0;
    }
 
    /**
     * Konstruktor s vychozi kapacitou (1000)
     */
    public Stack(){
        this(1000);
    }
 
    /**
     * Vlozi prvek na vrchol zasobniku
     * @param element prvek, ktery ma byt ulozen
     */
    public void push(int element){
        if (index >= getCapacity()){
            throw new StackFullException(getCapacity());
        }
        storage[index] = element;
        index ++;
    }
 
    /**
     * Vyjme prvek z vrcholu zasobniku a vrati jej
     * @return vyjmuty prvek
     */
    public int pop(){
        if (index <= 0){
            throw new EmptyStackException();
        }
        index --;
        return storage[index];
    }
 
    /**
     * Vrati celkovou kapacitu zasobniku
     * @return celkovou kapacitu zasobniku
     */
    public int getCapacity(){
        return storage.length;
    }
 
    /**
     * Vraci obsazenost zasobniku
     * @return pocet prvku na zasobniku
     */
    public int getCount(){
        return index;
    }
}

SmartStack.java

Vylepšený zásobník. Všimněte si, že zde by udržování kapacity ve speciální proměnné už mohlo přinést problémy. Pokud bychom zapomněli aktualizovat kapacitu nebo ji změnili nikoliv v souladu s délkou úložného pole, dostali bychom náš zásobník do nekonzistentního stavu. Zde je samozřejmé všechny proměnné uchovat nepřístupné pro uživatele třídy.

package stack;
 
import java.util.Arrays;
 
public class SmartStack extends Stack {
 
    /**
     * Konstuktor zasobniku s vychozi pocatecni kapacitou (1000)
     */
    public SmartStack() {
        super();
    }
 
    /**
     * Konstruktor s volitelnou pocatecni kapacitou
     * @param cap pocatecni kapacita zasobniku
     */
    public SmartStack(int cap) {
        super(cap);
    }
 
    /**
     * Zvetsi kapacitu zasobniku o inkrement
     * @param increment inkrement zvetseni kapacity zasobniku
     */
    protected void enlargeCapacity(int increment) {
        storage = Arrays.copyOf(storage, storage.length + increment);
        System.out.println("Enlarging to: " + storage.length);
    }
 
    /**
     * Prekryte push, pokud vlozeni prvku selze, zvetsi zasobnik
     * a zkusi prvek vlozit znovu.
     * @param element vkladany prvek
     */
    @Override
    public void push(int element) {
        try {
            super.push(element);
        } catch (StackFullException ex) {
            enlargeCapacity(getCapacity());
            super.push(element);
        }
    }
}

Stack2.java

Na třídě Stack2 naopak ilustrujeme opačný případ. Pro vytvoření zásobníku použijeme třídu ArrayList, což je implementace dynamicky se natahujícího pole. Dědění by v tomto případě “vylepšilo” zásobník o dvě metody, push a pop, ale nechalo by přístupné všechny metody, které poskytoval ArrayList, takže bychom mohli při použití zásobníku “podvádět” přístupem přes tyto metody.

Překrýt všechny metody a nastavit je na private nelze - Java to nedovolí. Modifikátory jsou informací pro překladač a kdyby tohle povolil, tak by to v runtimu šlo obejít.

Řešení je “zabalit” ArrayList do naší třídy a zprostředkovat jen operace, které chceme. Konceptu, kdy si funkčnost objektu poskládáme z jiných, se překvapivě říká skládání.

package stack;
 
import java.util.ArrayList;
 
public class Stack2 {
    private ArrayList<Integer> storage = new ArrayList<Integer>();
 
    public void push(int element){
        storage.add(new Integer(element));
    }
 
    public int pop(){
        return storage.remove(storage.size()-1).intValue();
    }
 
    public int getCount(){
        return storage.size();
    }
}

Main.java

package stack;
 
public class Main {
    public static void main (String [] args){
        Stack2 stack = new Stack2();
        /*
         * Zkuste vymenit
         * Stack stack = new Stack(4);
         * Stack stack = new SmartStack(4);
         */
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        stack.push(5);
        stack.push(6);
        stack.push(7);
        while (stack.getCount()>0){
            System.out.println(stack.pop());
        }
    }
}
pjvomo/stack.txt · Last modified: 2011/08/16 22:33 (external edit)
Back to top
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0