ITnetwork summer 2020
Pouze tento týden sleva až 80 % na e-learning týkající se Pythonu
80 % bodů zdarma na online výuku díky naší Letní akci!

Lekce 8 - Aréna s mágem (dědičnost a polymorfismus)

V minulé lekci, Dědičnost a polymorfismus, jsme si vysvětlili dědičnost a polymorfismus.

Dnes máme slíbeno, že si je vyzkoušíme v praxi. Bude to opět na naší aréně, kde z bojovníka oddědíme mága. Tento tutoriál již patří k těm náročnějším a bude tomu tak i u dalších. Proto si průběžně procvičujte práci s objekty, zkoušejte si naše cvičení a také vymýšlejte nějaké své aplikace, abyste si zažili základní věci. To, že je tu přítomen celý seriál neznamená, že ho celý najednou přečtete a pochopíte :) Snažte se programovat průběžně.

Mág

Než začneme něco psát, shodněme se na tom, co by měl mág umět. Mág bude fungovat stejně, jako bojovník. Kromě života bude mít však i manu. Zpočátku bude mana plná. V případě plné many může mág vykonat magický útok, který bude mít pravděpodobně vyšší damage, než útok normální (ale samozřejmě záleží na tom, jak si ho nastavíme). Tento útok manu vybije na 0. Každé kolo se bude mana zvyšovat o 10 a mág bude podnikat jen běžný útok. Jakmile se mana zcela doplní, opět bude moci magický útok použít. Mana bude zobrazena grafickým ukazatelem, stejně jako život.

Vytvoříme tedy třídu Mag.java, zdědíme ji z Bojovnik a dodáme ji atributy, které chceme oproti bojovníkovi navíc. Bude tedy vypadat takto (opět si ji okomentujte):

class Mag extends Bojovnik {
    private int mana;
    private int maxMana;
    private int magickyUtok;
}

V mágovi nemáme zatím přístup ke všem proměnným, protože jsou v bojovníkovi nastavené jako privátní. Musíme třídu Bojovnik lehce upravit. Změníme modifikátory private u atributů na protected. Budeme potřebovat jen kostka a jmeno, ale klidně nastavíme jako protected všechny atributy charakteru, protože se v budoucnu mohou hodit, kdybychom se rozhodli oddědit další typy bojovníků. Naopak atribut zprava není vhodné nastavovat jako protected, protože nesouvisí s bojovníkem, ale s nějakou vnitřní logikou třídy. Třída tedy bude vypadat nějak takto:

protected String jmeno;
protected int zivot;
protected int maxZivot;
protected int utok;
protected int obrana;
protected Kostka kostka;
private String zprava;

...

Přejděme ke konstruktoru.

Konstruktor potomka

Java nedědí konstruktory! Je to pravděpodobně z toho důvodu, že předpokládá, že potomek bude mít navíc nějaké atributy a původní konstruktor by u něj byl na škodu. To je i náš případ, protože konstruktor mága bude brát oproti tomu z bojovníka navíc 2 parametry (mana a magický útok).

Definujeme si tedy konstruktor v potomkovi, který bere parametry potřebné pro vytvoření bojovníka a několik parametrů navíc pro mága.

O potomků je nutné vždy volat konstruktor předka. Je to z toho důvodu, že bez volání konstruktoru nemusí být instance správně inicializovaná. Konstruktor předka nevoláme pouze v případě, že žádný nemá. Náš konstruktor musí mít samozřejmě všechny parametry potřebné pro předka plus ty nové, co má navíc potomek. Některé potom předáme předkovi a některé si zpracujeme sami. Konstruktor předka se vykoná před naším konstruktorem.

V Javě existuje klíčové slovo super, které je podobné námi již známému this. Na rozdíl od this, které odkazuje na konkrétní instanci třídy, super odkazuje na předka. My tedy můžeme zavolat konstruktor předka s danými parametry a poté vykonat navíc inicializaci pro mága.

Konstruktor mága bude tedy vypadat takto:

public Mag(String jmeno, int zivot, int utok, int obrana, Kostka kostka, int mana, int magickyUtok) {
    super(jmeno, zivot, utok, obrana, kostka);
    this.mana = mana;
    this.maxMana = mana;
    this.magickyUtok = magickyUtok;
}

Pozn. stejně můžeme volat i jiný konstruktor v té samé třídě (ne předka), jen místo super použijeme this.

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Přesuňme se nyní do Arena.java a druhého bojovníka (Shadow) změňme na mága, např. takto:

Bojovnik gandalf = new Mag("Gandalf", 60, 15, 12, kostka, 30, 45);

Změnu samozřejmě musíme udělat i v řádku, kde bojovníka do arény vkládáme. Všimněte si, že mága ukládáme do proměnné typu Bojovnik. Nic nám v tom nebrání, protože bojovník je jeho předek. Stejně tak si můžeme typ proměnné změnit na Mag. Když aplikaci nyní spustíme, bude fungovat úplně stejně, jako předtím. Mág vše dědí z bojovníka a zatím tedy funguje jako bojovník.

Polymorfismus a přepisování metod

Bylo by výhodné, kdyby objekt Arena mohl s mágem pracovat stejným způsobem jako s bojovníkem. My již víme, že takovémuto mechanismu říkáme polymorfismus. Aréna zavolá na objektu metodu utoc() se soupeřem v parametru. Nestará se o to, jestli bude útok vykonávat bojovník nebo mág, bude s nimi pracovat stejně. U mága si tedy přepíšeme metodu utoc() z předka. Přepíšeme zděděnou metodu tak, aby útok pracoval s manou, hlavička metody však zůstane stejná.

Když jsme u metod, budeme v Bojovnik.java ještě jistě používat metodu nastavZpravu(), ta je však privátní. Označme ji jako protected:

protected void nastavZpravu(String zprava) {

Pozn. Při návrhu bojovníka jsme samozřejmě měli myslet na to, že se z něj bude dědit a již označit vhodné atributy a metody jako protected. V tutoriálu k bojovníkovi jsem vás tím však nechtěl zbytečně zatěžovat, proto musíme modifikátory změnit až teď, kdy jim rozumíme :)

Pojďme přepsat utoc() bojovníka v mágovi. Metodu normálně definujeme v Mag.java tak, jak jsme zvyklí, pouze ji označíme @Override:

@Override
public void utoc(Bojovnik souper) {

Podobně jsme přepisovali metodu toString() u našich objektů, každý objekt v Javě je totiž odděděný od java.lang.Object, který obsahuje několik defaultních metod a jedna z nich je i toString(). Při její implementaci bychom tedy měli označit, že se jedná o přepsanou metodu.

Chování metody utoc() nebude nijak složité. Podle hodnoty many buď provedeme běžný útok nebo útok magický. Hodnotu many potom buď zvýšíme o 10 nebo naopak snížíme na 0 v případě magického útoku.

@Override
public void utoc(Bojovnik souper) {
    int uder = 0;
    // Mana není naplněna
    if (mana < maxMana) {
        mana += 10;
        if (mana > maxMana) {
            mana = maxMana;
        }
        uder = utok + kostka.hod();
        nastavZpravu(String.format("%s útočí s úderem za %s hp", jmeno, uder));
    } else { // Magický útok
        uder = magickyUtok + kostka.hod();
        nastavZpravu(String.format("%s použil magii za %s hp", jmeno, uder));
        mana = 0;
    }
    souper.branSe(uder);
}

Kód je asi srozumitelný. Všimněte si omezení many na maxMana, může se nám totiž stát, že tuto hodnotu přesáhneme, když ji zvyšujeme o 10. Když se nad kódem zamyslíme, tak útok výše v podstatě vykonává původní metoda utoc(). Jistě by bylo přínosné zavolat podobu metody na předkovi místo toho, abychom chování opisovali. K tomu opět použijeme super:

    @Override
    public void utoc(Bojovnik souper) {
    // Mana není naplněna
    if (mana < maxMana) {
    mana += 10;
    if (mana > maxMana) {
        mana = maxMana;
    }
    super.utoc(souper);
    } else { // Magický útok
    int uder = magickyUtok + kostka.hod();
    nastavZpravu(String.format("%s použil magii za %s hp", jmeno, uder));
    souper.branSe(uder);
    mana = 0;
    }
    }
import java.util.Random;
public class Kostka {
    private Random random;
    private int pocetSten;

    public Kostka() {
    pocetSten = 6;
    random = new Random();
    }

    public Kostka(int pocetSten) {
    this.pocetSten = pocetSten;
    random = new Random();
    }

    public int vratPocetSten() {
    return pocetSten;
    }

    public int hod() {
    return random.nextInt(pocetSten) + 1;
    }

    @Override
    public String toString() {
    return String.format("Kostka s %s stěnami", pocetSten);
    }
}
class Bojovnik {
    protected String jmeno;
    protected int zivot;
    protected int maxZivot;
    protected int utok;
    protected int obrana;
    protected Kostka kostka;
    private String zprava;

    public Bojovnik(String jmeno, int zivot, int utok, int obrana, Kostka kostka) {
    this.jmeno = jmeno;
    this.zivot = zivot;
    this.maxZivot = zivot;
    this.utok = utok;
    this.obrana = obrana;
    this.kostka = kostka;
    }

    public boolean nazivu() {
     return (zivot > 0);
    }

    public String grafickyZivot() {
    String s = "[";
    int celkem = 20;
    double pocet = Math.round(((double)zivot / maxZivot) * celkem);
    if ((pocet == 0) && (nazivu())) {
        pocet = 1;
    }
    for (int i = 0; i < pocet; i++) {
        s += "#";
    }
    for (int i = 0; i < celkem - pocet; i++) {
        s += " ";
    }
    s += "]";
    return s;
    }

    public void utoc(Bojovnik souper) {
    int uder = utok + kostka.hod();
    nastavZpravu(String.format("%s útočí s úderem za %s hp", jmeno, uder));
    souper.branSe(uder);
    }

    public void branSe(int uder) {
    int zraneni = uder - (obrana + kostka.hod());
    if (zraneni > 0) {
        zivot -= zraneni;
        zprava = String.format("%s utrpěl poškození %s hp", jmeno, zraneni);
        if (zivot <= 0) {
        zivot = 0;
        zprava += " a zemřel";
        }
    } else
        zprava = String.format("%s odrazil útok", jmeno);
        nastavZpravu(zprava);
    }

    protected void nastavZpravu(String zprava) {
    this.zprava = zprava;
    }

    public String vratPosledniZpravu() {
    return zprava;
    }

    @Override
    public String toString() {
    return jmeno;
    }

}
class Arena {
    private Bojovnik bojovnik1;
    private Bojovnik bojovnik2;
    private Kostka kostka;

    public Arena(Bojovnik bojovnik1, Bojovnik bojovnik2, Kostka kostka) {
    this.bojovnik1 = bojovnik1;
    this.bojovnik2 = bojovnik2;
    this.kostka = kostka;
    }

    private void vykresli() {
    System.out.println("-------------- Aréna -------------- \n");
    System.out.println("Zdraví bojovníků: \n");
    System.out.printf("%s %s\n", bojovnik1, bojovnik1.grafickyZivot());
    System.out.printf("%s %s\n", bojovnik2, bojovnik2.grafickyZivot());
    }

    private void vypisZpravu(String zprava) {
    System.out.println(zprava);
    try {
        Thread.sleep(500);
    } catch (InterruptedException ex) {
      System.err.println("Chyba, nepovedlo se uspat vlákno");
    }
    }

    public void zapas() {
    // původní pořadí
    Bojovnik b1 = bojovnik1;
    Bojovnik b2 = bojovnik2;
    System.out.println("Vítejte v aréně!");
    System.out.printf("Dnes se utkají %s s %s! \n\n", bojovnik1, bojovnik2);
    // prohození bojovníků
    boolean zacinaBojovnik2 = (kostka.hod() <= kostka.vratPocetSten() / 2);
    if (zacinaBojovnik2) {
        b1 = bojovnik2;
        b2 = bojovnik1;
    }
    System.out.printf("Začínat bude bojovník %s! \n\nZápas může začít...\n", b1);

    // cyklus s bojem
    while (b1.nazivu() && b2.nazivu()) {
        b1.utoc(b2);
        vykresli();
        vypisZpravu(b1.vratPosledniZpravu()); // zpráva o útoku
        vypisZpravu(b2.vratPosledniZpravu()); // zpráva o obraně
        if (b2.nazivu()) {
        b2.utoc(b1);
        vykresli();
        vypisZpravu(b2.vratPosledniZpravu()); // zpráva o útoku
        vypisZpravu(b1.vratPosledniZpravu()); // zpráva o obraně
        }
        System.out.println();
    }
    }
}

Opět vidíme, jak můžeme znovupoužívat kód. S dědičností je spojeno opravdu mnoho technik, jak si ušetřit práci. V našem případě to ušetří několik řádků, ale u většího projektu by to mohlo mít obrovský význam.

Aplikace nyní funguje tak, jak má.

Konzolová aplikace
-------------- Aréna --------------

Zdraví bojovníků:

Zalgoren [#############       ]
Gandalf [#################   ]
Gandalf použil magii za 52 hp
Zalgoren utrpěl poškození 36 hp

Arena nás však neinformuje o maně mága, pojďme to napravit. Přidáme mágovi veřejnou metodu grafickaMana(), která bude obdobně jako u života vracet String s grafickým ukazatelem many.

Abychom nemuseli logiku se složením ukazatele psát dvakrát, upravíme metodu grafickyZivot() v Bojovnik.java. Připomeňme si, jak vypadá:

public String grafickyZivot() {
    String s = "[";
    int celkem = 20;
    double pocet = Math.round(((double)zivot / maxZivot) * celkem);
    if ((pocet == 0) && (nazivu())) {
        pocet = 1;
    }
    for (int i = 0; i < pocet; i++) {
        s += "#";
    }
        s = String.format("%1$-" + (celkem + 1) + "s", s);
    s += "]";
    return s;
}

Vidíme, že není kromě proměnných zivot a maxZivot na životě nijak závislá. Metodu přejmenujeme na grafickyUkazatel a dáme ji 2 parametry: aktuální hodnotu a maximální hodnotu. zivot a maxZivot v těle metody poté nahradíme za aktualni a maximalni. Modifikátor bude protected, abychom metodu mohli v potomkovi použít:

protected String grafickyUkazatel(int aktualni, int maximalni) {
    String s = "[";
    int celkem = 20;
    double pocet = Math.round(((double)aktualni / maximalni) * celkem);
    if ((pocet == 0) && (nazivu())) {
        pocet = 1;
    }
    for (int i = 0; i < pocet; i++) {
        s += "#";
    }
        s = String.format("%1$-" + (celkem + 1) + "s", s);
    s += "]";
    return s;
}

Metodu grafickyZivot() v Bojovnik.java naimplementujeme znovu, bude nám v ní stačit jediný řádek a to zavolání metody grafickyUkazatel() s příslušnými parametry:

public String grafickyZivot() {
    return grafickyUkazatel(zivot, maxZivot);
}

Určitě jsem mohl v tutoriálu s bojovníkem udělat metodu grafickyUkazatel() rovnou. Chtěl jsem však, abychom si ukázali, jak se řeší případy, kdy potřebujeme vykonat podobnou funkčnost vícekrát. S takovouto parametrizací se v praxi budete setkávat často, protože nikdy přesně nevíme, co budeme v budoucnu od našeho programu požadovat.

Nyní můžeme vykreslovat ukazatel tak, jak se nám to hodí. Přesuňme se do Mag.java a naimplementujme metodu grafickaMana():

public String grafickaMana() {
    return grafickyUkazatel(mana, maxMana);
}

Jednoduché, že? Nyní je mág hotový, zbývá jen naučit arénu zobrazovat manu v případě, že je bojovník mág. Přesuňme se tedy do Arena.

Rozpoznání typu objektu

Jelikož se nám nyní vykreslení bojovníka zkomplikovalo, uděláme si na něj samostatnou metodu vypisBojovnika(), jejím parametrem bude daná instance bojovníka:

private void vypisBojovnika(Bojovnik b) {
    System.out.println(b);
    System.out.print("Zivot: ");
    System.out.println(b.grafickyZivot());
}

Nyní pojďme reagovat na to, jestli je bojovník mág. Minule jsme si řekli, že k tomu slouží operátor instanceof:

private void vypisBojovnika(Bojovnik b) {
    System.out.println(b);
    System.out.print("Zivot: ");
    System.out.println(b.grafickyZivot());
    if (b instanceof Mag) {
        System.out.print("Mana:  ");
        System.out.println(((Mag)b).grafickaMana());
    }
}

Bojovníka jsme museli na mága přetypovat, abychom se k metodě grafickaMana() dostali. Samotný Bojovnik ji totiž nemá. To bychom měli, vypisBojovnika budeme volat v metodě vykresli(), která bude vypadat takto:

    private void vykresli() {
    System.out.println("-------------- Aréna -------------- \n");
    System.out.println("Bojovníci: \n");
    vypisBojovnika(bojovnik1);
    System.out.println();
    vypisBojovnika(bojovnik2);
    System.out.println();
    }
class Bojovnik {
    protected String jmeno;
    protected int zivot;
    protected int maxZivot;
    protected int utok;
    protected int obrana;
    protected Kostka kostka;
    private String zprava;

    public Bojovnik(String jmeno, int zivot, int utok, int obrana, Kostka kostka) {
    this.jmeno = jmeno;
    this.zivot = zivot;
    this.maxZivot = zivot;
    this.utok = utok;
    this.obrana = obrana;
    this.kostka = kostka;
    }

    public boolean nazivu() {
     return (zivot > 0);
    }

    protected String grafickyUkazatel(int aktualni, int maximalni) {
    String s = "[";
    int celkem = 20;
    double pocet = Math.round(((double)aktualni / maximalni) * celkem);
    if ((pocet == 0) && (nazivu())) {
        pocet = 1;
    }
    for (int i = 0; i < pocet; i++) {
        s += "#";
    }
    s = String.format("%1$-" + (celkem + 1) + "s", s);
    s += "]";
    return s;
    }

    public String grafickyZivot() {
    return grafickyUkazatel(zivot, maxZivot);
    }

    public void utoc(Bojovnik souper) {
    int uder = utok + kostka.hod();
    nastavZpravu(String.format("%s útočí s úderem za %s hp", jmeno, uder));
    souper.branSe(uder);
    }

    public void branSe(int uder) {
    int zraneni = uder - (obrana + kostka.hod());
    if (zraneni > 0) {
         zivot -= zraneni;
         zprava = String.format("%s utrpěl poškození %s hp", jmeno, zraneni);
         if (zivot <= 0) {
         zivot = 0;
         zprava += " a zemřel";
         }
    } else
        zprava = String.format("%s odrazil útok", jmeno);
        nastavZpravu(zprava);
    }

    protected void nastavZpravu(String zprava) {
    this.zprava = zprava;
    }

    public String vratPosledniZpravu() {
    return zprava;
    }

    @Override
    public String toString() {
    return jmeno;
    }
}
class Mag extends Bojovnik {
    private int mana;
    private int maxMana;
    private int magickyUtok;

    public Mag(String jmeno, int zivot, int utok, int obrana, Kostka kostka, int mana, int magickyUtok)
    {
    super(jmeno, zivot, utok, obrana, kostka);
    this.mana = mana;
    this.maxMana = mana;
    this.magickyUtok = magickyUtok;
    }

    @Override
    public void utoc(Bojovnik souper) {
    // Mana není naplněna
    if (mana < maxMana) {
         mana += 10;
         if (mana > maxMana) {
         mana = maxMana;
        }
         super.utoc(souper);
    } else { // Magický útok
         int uder = magickyUtok + kostka.hod();
         nastavZpravu(String.format("%s použil magii za %s hp", jmeno, uder));
         souper.branSe(uder);
         mana = 0;
    }
    }

     public String grafickaMana() {
    return grafickyUkazatel(mana, maxMana);
    }
}


Hotovo :)

Konzolová aplikace
-------------- Aréna --------------

Bojovníci:

Zalgoren
Život: [##########          ]

Gandalf
Život: [#####               ]
Mana: [#############       ]

Zalgoren útočí s úderem za 28 hp

Aplikaci ještě můžeme dodat hezčí vzhled, vložil jsem ASCIIart nadpis Aréna, který jsem vytvořil touto aplikací: http://patorjk.com/software/taag . Metodu k vykreslení ukazatele jsem upravil tak, aby vykreslovala plný obdelník místo # (ten napíšete pomocí Alt + 219). Výsledek může vypadat takto:

Konzolová aplikace
   __    ____  ____  _  _    __
  /__\  (  _ \( ___)( \( )  /__\
 /(__)\  )   / )__)  )  (  /(__)\
(__)(__)(_)\_)(____)(_)\_)(__)(__)

Bojovníci:

Zalgoren
Život: ████

Gandalf
Život: ███████
Mana:  █

Gandalf použil magii za 48 hp
Zalgoren utrpěl poškození 33 hp

Kód máte v příloze. Pokud jste něčemu nerozuměli, zkuste si článek přečíst vícekrát nebo pomaleji, jsou to důležité praktiky.

V následujícím cvičení, Řešené úlohy k 5. - 8. lekci OOP v Javě, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

Stáhnout

Staženo 1145x (31.13 kB)
Aplikace je včetně zdrojových kódů v jazyce java

 

Předchozí článek
Dědičnost a polymorfismus
Všechny články v sekci
Objektově orientované programování v Javě
Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
33 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity (13)

 

 

Komentáře

Avatar
tomasfurch
Člen
Avatar
tomasfurch:9.10.2012 0:07

Chyba u konstruktoru. Pokud má rodič konstruktor s alespoň jedním parametrem, tak potomek musí mít konstruktor, jehož první příkaz bude super(), kterým volá konstruktor rodiče. Takže věta "Toto je jistě funkční konstruktor k vytvoření mága." je "trochu" zavádějící, protože se to nezkompiluje.

 
Odpovědět
9.10.2012 0:07
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na tomasfurch
David Čápka:9.10.2012 10:40

Díky, seriál je portovaný z C#, i když jsme vše zkoušeli a odlišnosti mezi jazyky jsou minimální, může se občas něco takového objevit, opravím :)

Edit: Opraveno

Editováno 9.10.2012 17:12
Odpovědět
9.10.2012 10:40
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
tomasfurch
Člen
Avatar
tomasfurch:9.10.2012 22:07

A ještě jedna drobnost. V metodě vykresli by se metoda vypisBojovnika() měla volat jako bojovnik1.vypis­Bojovnika(bojov­nik1); respektive bojovnik2.vypis­Bojovnika();.

 
Odpovědět
9.10.2012 22:07
Avatar
MalRa
Člen
Avatar
MalRa:26.10.2012 11:41

Zdavím. Chyba v implementaci metody utoc(). Namísto base.utoc(souper); by tam mělo být super.utoc(souper); :). Mějte se.

 
Odpovědět
26.10.2012 11:41
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na MalRa
David Čápka:26.10.2012 12:12

Díky, opraveno :)

Odpovědět
26.10.2012 12:12
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
domino.turak
Člen
Avatar
domino.turak:11.6.2013 12:40

Ja len taká miniaturná chybička vypisBojovnika je metoda deklarovana s malym začiatočným písmenom, vo vykreslení() je však volaná VypisBojovnika, takže tam to bude hlásiť chybičku myslím :)

Odpovědět
11.6.2013 12:40
"Never give up!"
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na domino.turak
David Čápka:11.6.2013 12:49

Díky, opraveno :)

Odpovědět
11.6.2013 12:49
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
domino.turak
Člen
Avatar
domino.turak:11.6.2013 14:39

Môžem sa ešte opýtať ako dať to Arena do mojho programu? na tej stránke si napíšem , skopírujem, ono sa mi to aj tam skopíruje ale hlási to chybu keďže to níe je na jednom riadku... ako si to urobil ty?

Odpovědět
11.6.2013 14:39
"Never give up!"
Avatar
hanse
Člen
Avatar
Odpovídá na domino.turak
hanse:11.6.2013 15:08

před uvozovky dej @

Console.WriteLine(@"jaký
koliv
text");

Když si nebudeš vědět rady, jak něco udělat, tak si stáhni zdrojový soubor (pod tutorialem)

Editováno 11.6.2013 15:08
 
Odpovědět
11.6.2013 15:08
Avatar
domino.turak
Člen
Avatar
domino.turak:11.6.2013 15:51

Tak uroibl som si osobitnu metodu na vykreslenie nadpisu po jednom riadku ... tak toto mam už pekne ale to nahradenie # týmto █ mi vypisovalo nejaké upozornenie, zaškrtol som niečo s UUT8 alebo niečo také a terza mi to vykresľuje ???? namiesto ███ , nejaká zmena v nastaveniach, ktorá by to opravila?

Odpovědět
11.6.2013 15:51
"Never give up!"
Avatar
domino.turak
Člen
Avatar
Odpovídá na hanse
domino.turak:11.6.2013 17:06

Nefunkčné, zrejme si si to pomýlil s nejakým iným jazykom, ale to nevadí lebo už som si to urobil po svojom :)

Odpovědět
11.6.2013 17:06
"Never give up!"
Avatar
domino.turak
Člen
Avatar
domino.turak:11.6.2013 17:16

Nevedel som,že keď chcem editovať príspevok tak mám nato nejaký časový limit, každopádne ešte som našiel jednu mikrochybičku. Aby ten program bol úplne totožný s tým, ako to má vyzerať, v metóde vypisBojovnika riadok System.out.prin­tln("Život :") bez toho ln :) ináč skvelý tutoriál naozaj, vlastne celý devbook je super :)

Odpovědět
11.6.2013 17:16
"Never give up!"
Avatar
Odpovídá na David Čápka
Libor Šimo (libcosenior):15.9.2013 10:31

Myslím, že by bolo dobré doplniť do metódy vykresli() nad ARENA vyčistenie plochy (ak je to možné), v c# to je urobené (Console.Clear();). Tu neviem príkaz.

Odpovědět
15.9.2013 10:31
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na Libor Šimo (libcosenior)
Libor Šimo (libcosenior):15.9.2013 11:01

Ešte by som chcel požiadať o vysvetlenie riadku v garfickyUkazatel()

s = String.format("%1$-" + (celkem + 1) + "s", s);

Viem, že vykresľuje život (manu), ale priznám sa, nerozumiem ako funguje.

Odpovědět
15.9.2013 11:01
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Libor Šimo (libcosenior)
David Čápka:15.9.2013 13:13

Řádek jen doplní mezery za ubytý život. Nevím, proč je to takhle divné, v dílu s bojovníkem je tam for cyklus. Asi to pak změním.

Odpovědět
15.9.2013 13:13
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Odpovídá na David Čápka
Libor Šimo (libcosenior):15.9.2013 14:28

Práve že neviem ako to funguje, som sa na to pýtal.
Nerozumiem tomuto:
("%1$-", s);

Odpovědět
15.9.2013 14:28
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
sisolpes
Člen
Avatar
sisolpes:3.12.2013 21:40

Mám potíž.
Když chci vložit text ASCIIart bere mi java znak \ jako další řádek, nikoli jako součást písmene.
Máte někdo radu?
Díky.

Odpovědět
3.12.2013 21:40
Alt + 2
Avatar
mnauik
Člen
Avatar
mnauik:18.12.2013 15:57

Ahoj, není lepší použít abstraktní třídu? Pokud není, tak proč? Děkuji.

Odpovědět
18.12.2013 15:57
minusuj mě, ale zdůvodni to ;)
Avatar
Matěj Kripner:10.2.2014 19:39

Nechci být hnidopich, ale pro přesnost :): v druhém překrytí metody utoc() máš

String.Format("%s použil magii za %s hp", jmeno, uder)

Nemělo by tam být malé f ?

Editováno 10.2.2014 19:39
Odpovědět
10.2.2014 19:39
Give me a deep enough pipeline, and I shall move the world.
Avatar
Matěj Kripner:10.2.2014 20:39

Jo, a taky bych se chtěl zeptat, proč je v tom samém řádku zástupná značka pro int uder %s místo %d ? Díky

Odpovědět
10.2.2014 20:39
Give me a deep enough pipeline, and I shall move the world.
Avatar
MrPabloz
Člen
Avatar
Odpovídá na mnauik
MrPabloz:10.2.2014 20:49

Protože kdyby sis projel všechny díly této části, zjistil bys, že tam je objekt typu bojovník, a mág je pouze potomek a bojovník bojuje proti mágovi pokud si dobře pamatuju, tedy bojovník se taky využívá proto nemá být abstraktní třída :)

Odpovědět
10.2.2014 20:49
Harmonie těla a duše, to je to, oč se snažím! :)
Avatar
Odpovídá na mnauik
Lukáš Hruda (Luckin):10.2.2014 20:55

Řekl bych, že to lepší je, ale abstraktní třídy jsou probírány až dál.

 
Odpovědět
10.2.2014 20:55
Avatar
simonovsky
Člen
Avatar
simonovsky:12.11.2014 16:48

Opět sem našel nějaké ty chyby, tak ať se aspoň upraví pro budoucí programátory:
1)

protected void nastavZpravu(string zprava)

místo string má být String

2)

@Override
public void utoc(Bojovnik souper)
{
        // Mana není naplněna
        if (mana < maxMana)
        {
                mana += 10;
                if (mana > maxMana)
                        mana = maxMana;
                super.utoc(souper);
        }
        else // Magický útok
        {
                int uder = magickyUtok + kostka.hod();
                nastavZpravu(String.Format("%s použil magii za %s hp", jmeno, uder));
                souper.branSe(uder);
                mana = 0;
        }
}

místo String.Format(..) má být String.format

 
Odpovědět
12.11.2014 16:48
Avatar
B42P6
Člen
Avatar
B42P6:19.5.2015 11:48

Zaujímalo by ma či je označenie @Override len pre informáciu (Ako Komentáre)
Lebo...aj keď tam @Override neni, program beží v poriadku.

Odpovědět
19.5.2015 11:48
'long long long' is too long for GCC
Avatar
Richard H.
Redaktor
Avatar
Richard H.:7.8.2015 14:50

Mas tam chybu objekty se v javě dědí od java.lang.object ne od System.object .
Nepsal jsi náhodou před timhle tutoriál na C# :D

Odpovědět
7.8.2015 14:50
Malý užitečný manuál je vždy lepší než bichle k ničemu.
Avatar
Petr Beneš
Člen
Avatar
Petr Beneš:3.9.2015 19:20

Mám jeden dotaz. Snažím se trochu si srovnat modifikátory přístupu a když na to tady teď koukám, tak si říkám, jestli nastavením protected na proměnných třídy bojovník nedošlo k přílišnému otevření. Původně tam bylo private, aby došlo k zapouzdření, ale po změně na protected mají k proměnným přístup i jiné classy ze stejného balíku.

Jediné jak si to dovedu vysvětlit je, že by se rodič měl tvořit v samostatném balíčku. A nebo to taky chápu úplně špatně a už jsem se tu do toho zamotal :-)

 
Odpovědět
3.9.2015 19:20
Avatar
Lukas C#
Redaktor
Avatar
Odpovídá na Petr Beneš
Lukas C#:3.9.2015 19:36

Nevím, co myslíš "balíčkem". Ale pokud je něco protected, tak je to vlastně pořád private, tzn. můžeš to použít jenom uvnitř své třídy, ale zároveň to lze dědit - jde to použít u potomka i u rodiče, ale furt jenom uvnitř třídy, nedostaneš se k tomu jinde.

 
Odpovědět
3.9.2015 19:36
Avatar
vosa53
Člen
Avatar
Odpovídá na Lukas C#
vosa53:3.9.2015 20:03

Je to asi javista, tam jsou balíčky (package) místo složek a protected funguje přesně tak jak popisuje. :)

 
Odpovědět
3.9.2015 20:03
Avatar
Zdeněk Pavlátka
Tým ITnetwork
Avatar
Odpovídá na Lukas C#
Zdeněk Pavlátka:3.9.2015 20:08

balíček == package

Odpovědět
3.9.2015 20:08
Kolik jazyků umíš, tolikrát jsi programátor.
Avatar
vosa53
Člen
Avatar
Odpovídá na Petr Beneš
vosa53:3.9.2015 20:08

To co říkáš funguje v Javě a možná i někde jinde, nevím. Ale v c# to funguje tak jak píše Lukas C# :)

 
Odpovědět
3.9.2015 20:08
Avatar
Petr Beneš
Člen
Avatar
Odpovídá na Lukas C#
Petr Beneš:4.9.2015 8:50

Jsem polichocen. Poprvé mě někdo nazval Javistou :-) Asi začnu používat výhradně anglické termíny, aby nedocházelo k omylům.

Po přečtení tohoto tutorialu jsem si myslel, že je to jak píše Lukas C#, ale na stránkách Oracle jsem se dočetl něco jiného:
https://docs.oracle.com/…control.html

Btw. díky za rychlé reakce. To jsem nečekal :-)

 
Odpovědět
4.9.2015 8:50
Avatar
Tomas Hlinovsky:9.12.2015 0:34

Zase skvělej díl, jenom mi ty ukazatele zdraví a many neladí (každej jinak dlouhej), což úplně nechápu...

 
Odpovědět
9.12.2015 0:34
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Tomas Hlinovsky:9.12.2015 1:15

Zajímavé je, že jakmile se vymění místo # ten plnej obdélník tak délka ukazatelů začne blbnout.

 
Odpovědět
9.12.2015 1:15
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:13.1.2016 13:08

Ve vzorových řešení máš malou hovadinu v Kostka.java. V přetíženém kostruktoru jednou implementuješ náhodonost včetně stěn, tak proč to potom porušuješ? Navíc ti chybí volání přetíženého konstruktoru.

public Kostka(){
        this.Kostka(6);                 //<-- zbytečná implementace
        random = new Random();  //<-- zbytečná implementace
        this(6);                                //<-- volání přetíženého konstruktoru, které zde chybí
}

public Kostka(int pocetSten){
        this.pocetSten = pocetStem();
        random = new Random();
}

Další - metoda hod(), podle této implementace může hodit i 7:) je tam jedna jednička navíc (otázka za jednoho bludišťáka: kterápak to asi bude?)

Ve třídě Bojovnik.java a Mag.java zase nemáš návratové metody pro atributy třídy - zivot a mana. Zase porušuješ zapouzdření.

Odpovědět
13.1.2016 13:08
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
svizensky
Člen
Avatar
Odpovídá na Lubor Pešek
svizensky:26.4.2016 13:38

Ta první ....

 
Odpovědět
26.4.2016 13:38
Avatar
Avev Frger
Člen
Avatar
Avev Frger:23.7.2016 17:41

V tele metody grafickyUkazatel ma podmienka

if ((pocet == 0) && (nazivu()))
  pocet = 1;

vyzerat nejako inak lebo pri zobrazovani many je ukazatel many zobrazeny pri malom mnozstve many nespravne ak mag zije.

 
Odpovědět
23.7.2016 17:41
Avatar
Avev Frger
Člen
Avatar
Odpovídá na Avev Frger
Avev Frger:23.7.2016 17:55

presnejsie po vycerpani many po utoku je zvysena o 1

Editováno 23.7.2016 17:57
 
Odpovědět
23.7.2016 17:55
Avatar
Jan Kunágl
Člen
Avatar
Jan Kunágl:23.8.2016 15:42

Zdravím, prosil bych o radu (pokročilejším se omlouvám, pro ty to bude prkotina). Celý projekt Tahovy boj je mi jakžtakž jasný, až na jednu maličkost. Jde mi o použití příkazu "return".
Vím, že když se volá nějaká metoda, aby např. vypočítala nějakou hodnotu, vrací se tato hodnota z této metody pomocí příkazu return.
Potom je další případ, že nějaká metoda volá jinou metodu, aby něco vykonala, což se v tomto tutorialu celkem běžně dělalo bez příkazu return ve volané metodě.
Další použití volání metody metodou v tomto tutorialu už mi právě jasné není. Jde o případ, že se volá nějaká metoda, která vykoná jenom to, že zavolá jinou metodu a předá jí nějaké parametry. Např.:

/*
    Metoda pro grafické ukázání stavu many mága */
    public String grafickaMana(){
        return grafickyUkazatel(mana, maxMana);//Volá M pro grafický výpis dodaných parametrů mateřské T Bojovník
    }

Proč je tam, když se z metody grafickaMana(), volá metoda grafickyUkazatel(), předtím to slovo return? Nejde přeci o to, aby poslední volaná metoda vrátila nějakou hodnotu, se kterou volající bude potom nějak pracovat, ale jde o vykonání celé posloupnosti příkazů ve volané metodě. Já chápu, že sama metoda grafickaMana() je taky volaná zase jinou metodou. Jde o to, že první volající metodě předá tato metoda tu poslední volanou metodu? A není v tom potom trochu zmatek? Nefungovalo by to i bez toho return (samozřejmě bych dal do hlavičky M potom slovo "void")? Já si myslím, že potom může být při psaní kódu docela zmatek v tom, kdy když z nějaké metody volám jinou metodu (což je, jak pozoruji, jedna z hlavních činností programu v javě), tak tam mám/nemám to "return" použít...

 
Odpovědět
23.8.2016 15:42
Avatar
pocitac770
Redaktor
Avatar
Odpovídá na Jan Kunágl
pocitac770:23.8.2016 18:43

Obecně my chceme metodami typu grafickyUkazatel -> grafickyZivot/gra­fickaMana získat String, který bude obsahovat grafické zobrazení našeho počtu životů/many. Představ si tuto konstrukci jako dědičnost (s trochou abstrakce, o tom se dovíš později). Máš jednu metodu (grafickyUkazatel), která slouží jako základ pro další metody (grafickyZivot, grafickaMana). Ty vždy pracují s jinými atributy, jednou se životem, jednou s manou, ale princip vykreslování přes trojčlenku (jestli si dobře pamatuju z dob, když jsem se to učil, teď jsem se na to nekoukal :D) je pokaždé stejný.
Trochu přimhouřím oči od své původní myšlenky, a přirovnám to k něčemu jinému. Třída-instance. Představ si třídu "Ukazatel", od které si vytvoříš 2 instance, jednu, která bude pracovat s životy, a jednu, která bude pracovat s manou, dejme tomu, že by jsme přes boxing průběžně předávali jejich hodnoty (ach ty pozdní znalosti, ignoruj mě :D), a pak by jsme nějak vraceli metodou String, který by samotný ukazatel "vykresloval". Když tak o tom přemýšlím, je to mnohem ladnější řešení, než to zdejší, ale to se stav na nedostatku znalostí.
K tomu return. Rád bych řekl TLDR, ale spíš musím říct, že jsem nepochopil, kde je problém. Return obecně ukončuje metodu a umožní metodu vrátit nějaký datový typ. Pokud metoda něco vrací (není void), tak si můžeme v kódě představit, jako by tam nebyla metoda, ale nějaký String, to jde například reálně použít při debugu, když chceš jenom otestovat třeba zarovnání a ještě nemáš hotovou logiku ukazatele, tak tam doplníš třeba

/*
    Metoda pro grafické ukázání stavu many mága */
    public String grafickaMana(){
        String s = "testovací řádek";
        return s;
    }

metoda vrací nějaký String, tudíž to přesně tak funguje. a když to máš v metodě, která taktéž vrací String, tak proč to prostě nepředat dál? Trochu rozsáhlejší typ problematiky by mohl být, kdyby jsi připravoval v metodě nějak ty parametry, třeba....

/*
    Metoda pro grafické ukázání FALEŠNÉHO #thugLife stavu many mága */
    public String grafickaFakeMana(){
        int fakeMana = mana + 10;
        return grafickyUkazatel(fakeMana, maxMana);//Volá M pro grafický výpis dodaných parametrů mateřské T Bojovník
    }

Pořád by jsi chtěl akorát předat ten výsledek metody, ale jakoby si "nascriptit" to, co se bude používat jako parametry, případně jak se budou ty parametry upravovat (viz výše), asi bude kratší v tuto chvíli napsat do kódu

String s = grafickaMana();

než

String s = grafickyUkazatel(mana, maxMana);

Takhle se to zdá jenom jako lenost, ale představ si situaci, kdy to bude něco podobného jako ta moje grafickaFakeMana, ale zpracování dat by zabralo třeba 10 řádků. To by pak byl v kódu bordel... Zdejší tutoriály se snaží lidi naučit myslet co nejefektivněji, a ukazují to na jednoduchých příkladech, aby si to vstříbili již od počátku...
Pff, doufám, že touhle vyčerpávající odpovědí jsem ti odpověděl na všechny otázky, ale kdyby něco bylo stále nejasné, klidně napiš :)

Editováno 23.8.2016 18:45
 
Odpovědět
23.8.2016 18:43
Avatar
Jan Kunágl
Člen
Avatar
Odpovídá na pocitac770
Jan Kunágl:23.8.2016 21:38

Ano, myslím, že to chápu.
V tomto případě vlastně chceme od metody (bez ohledu na to, že voláním jiné M) aby nám vrátila hodnotu - řetězec, proto to return, kterým si zároveň i tu metodu, ukončíme.
Způsob, jakým se tato metoda k výsledku dostane, tj. v tomto případě voláním další, obecnější metody, které předá "svoje" parametry, je jenom efektivnějším způsobem, jak nevyrábět další zbytečné metody pro něco, pro co už metoda je.
Ale stejně si to zkusím :-), co to udělá, když tam to return nedám a M grafickyUkazatel() v M grafickaMana() jen zavolám, bez toho return, jestli bude program fungovat, případně, že se M grafickyUkazatel() sice vykoná, ale program se tím předčasně ukončí. Každopádně dám vědět, jak to dopadlo.

Děkuji moc za tvojí reakci, která mi dala, kromě odpovědi i další podněty k přemýšlení :-)

 
Odpovědět
23.8.2016 21:38
Avatar
pocitac770
Redaktor
Avatar
Odpovídá na Jan Kunágl
pocitac770:23.8.2016 23:13

Vím, že na to určtě přijdeš sám, ale radši dám menší nápovědu, je to vlastně úplně to samé, jako napsat

int i = 2;
i + 5;

kompilátor ti to sice vyhodí jako chybu, tohle je totální nesmysl, ale jaksi by to tomu odpovídalo, jak by to fungovalo i v tomto případě (upřímně to sám nechápu, mě to zní jako docela logický statement). To, co popisuješ je používáno v různých frameworcích/kni­hovnách, které jsou pro programátory vytvořené, aby je sami nějakým svým způsobem použili. Dejme tomu, že existuje metoda .mkdir(), která vytváří složku. Vypadá to nějak takto.

mojeSlozka.mkdir();

Funguje to, úplně bezchybně, ALE! většinou je to používáno takto

if(!mojeSlozka.mkdir()){
        //nějaký další kód, viz další lekce ;)
}

Kde se z ničeho nic ta booleanová hodnota vzala? Ona tam byla i předtím, akorát jsme ji nijak nevyužili, nezajímala nás. V druhém příkladě jsme ji naopak kvůli něčemu potřebovali, tak jsme si ji zjistili, jaká vlastně je, a podle toho zareagovali, nějak jsme ji použili.

Editováno 23.8.2016 23:16
 
Odpovědět
23.8.2016 23:13
Avatar
Jan Kunágl
Člen
Avatar
Jan Kunágl:24.8.2016 14:23

Takže jsem zkusil vynechat to return a metodu:

public String grafickaMana(){
    return grafickyUkazatel(mana, maxMana);//Volá M pro grafický výpis dodaných parametrů mateřské T Bojovník
}

upravil do této podoby:

public void grafickaMana(){
        grafickyUkazatel(mana, maxMana);//Volá M pro grafický výpis dodaných parametrů mateřské T Bojovník
    }

Kompilátor to vynechání return vyhodnotil jako chybu, ještě před spuštěním programu. Jako chybná byla označena ne M grafickaMana(), ale původní příkaz tuto metodu volající:

System.out.println(((Mag)b).grafickaMana());

Myslím, že to byla jenom moje základní chyba a neuvědomění si faktu, že příkaz System.out.prin­tln() prostě vyžaduje jako argument řetězec a ne vykonání nějaké metody, která volá další metodu, bez vrácení toho String pomocí return v té volající metodě:-)

Takže jestli jsem tě dobře pochopil, když máme např. nějaký výraz (metodu), může být rozdíl ve způsobu, jak jej použijeme a co z něj chceme dostat. A to je ten základní kámen úrazu - nemíchat potom hrušky a jablka.
No nic budu o tom ještě nějakou chvíli přemýšlet, snad se do toho nezamotám :-)

Děkuji moc za užitečné odpovědi!

 
Odpovědět
24.8.2016 14:23
Avatar
David
Člen
Avatar
Odpovídá na Avev Frger
David:25.9.2016 22:48

Já to vyřešil v rychlosti tak, že jsem podmínku odstranil a použil zaokrouhlení nahoru, nechtělo se mi s tím víc zdržovat.
Navíc jsem úplnej začátečník, takže se mi ani do ničeho složitějšího pouštět nechtělo. :)

 
Odpovědět
25.9.2016 22:48
Avatar
Marek Zelený
Redaktor
Avatar
Marek Zelený:23.10.2017 19:25

Mám dotaz týkající se konstruktoru při dědění. V článku je tento kód:

public Mag(String jmeno, int zivot, int utok, int obrana, Kostka kostka, int mana, int magickyUtok) {
        super(jmeno, zivot, utok, obrana, kostka);
        this.mana = mana;
        this.maxMana = mana;
        this.magickyUtok = magickyUtok;
}

Znamená to, že můžu předkův konstruktor zavolat kdekoliv v těle konstruktoru potomka, klidně i na konci? Třeba takhle:

public Mag(String jmeno, int zivot, int utok, int obrana, Kostka kostka, int mana, int magickyUtok) {
        this.mana = mana;
        this.maxMana = mana;
        this.magickyUtok = magickyUtok;
        super(jmeno, zivot, utok, obrana, kostka);
}

C# to (pokud vím) neumožňuje, protože se konstruktor předka volá ještě před tělem potomkova konstruktoru, ale už jsem několikrát narazil na situaci, kdy by se mi více hodilo spustit ho až po vykonání jiné části kódu (musel jsem to různě obcházet, ale nevypadalo to moc hezky).

 
Odpovědět
23.10.2017 19:25
Avatar
gcx11
Redaktor
Avatar
Odpovídá na Marek Zelený
gcx11:23.10.2017 20:02

Ne, nemůžeš:
https://stackoverflow.com/…-constructor

A docela by mě zajímalo, v jakém případě jsi to potřeboval, vůbec mě nenapadá, k čemu by se to mohlo hodit.

 
Odpovědět
23.10.2017 20:02
Avatar
Marek Zelený
Redaktor
Avatar
Odpovídá na gcx11
Marek Zelený:23.10.2017 21:05

Díky za odpověď i za odkaz :-)

Co se týče použití, když jsem začínal s OOP, zkoušel jsem si naprogramovat šachy. Měl jsem třídu Figurka, ze které jsem dědil jednotlivé typy figurek. Při vytvoření jsem jim přiřadil pozici na šachovnici, ta ale záležela na barvě figurky. Musel jsem potom u každého typu figurky do konstruktoru napsat prakticky stejný kód, který pracoval s již určenou pozicí.
Dneska bych to asi vyřešil nějakou metodou, ale tehdy mě to nenapadlo a hrozně mě štvalo, že nemůžu ten předkův konstruktor spustit až na konci. Mám pocit, že jsem na to narazil ještě někde, ale už si nevzpomenu kde.

 
Odpovědět
23.10.2017 21:05
Avatar
Tonda Đình Hoàng:30.12.2017 15:56

Nevíte proč u mága není
maxZivot = zivot;

Děkuju moc

 
Odpovědět
30.12.2017 15:56
Avatar
dez1nd
Člen
Avatar
Odpovídá na Tonda Đình Hoàng
dez1nd:2.1.2018 7:57

Jestli vidím dobře, je to z důvodu, že hodnotu zivot zdědil z bojovnika

class Mag extends Bojovnik {
        private int mana;
        private int maxMana;
        private int magickyUtok;
}

jen tyto 3 atributy má navíc, ostatní zdědil

Editováno 2.1.2018 7:57
 
Odpovědět
2.1.2018 7:57
Avatar
Radka Jánská:3.3.2018 21:46

Ahoj! Chtěla bych se zeptat, jak můžu naprogramovanou hru spustit jako uživatel? Dejme tomu ji pošlu kamarádce, aby ji vyzkoušela ... samozřejmě nemá NetBeans ani jiné IDE ... díky za předem za odpovědi!

 
Odpovědět
3.3.2018 21:46
Avatar
zitekv
Člen
Avatar
Odpovídá na Radka Jánská
zitekv:4.3.2018 10:56

Ahoj,
aby si to mohla kamarádka spustit musí mít nainstalován JVM (java virtual machine nebo jinak JRE java runtime enviroment) a pomocí tohoto si spustí soubor tvojeAplikace.jar, který jí pošleš.
Více informací třeba zde

 
Odpovědět
4.3.2018 10:56
Avatar
Radka Jánská:23.4.2018 22:15

Ahoj, mam dotaz. Je tu psano, ze potomek vzdy musi volat konstruktor predka. Co kdyz ma predek pretizeny konstruktor? Co pak ma volat? Muzu si proste vybrat ten konstruktor, co se mi hodi? Diky.

 
Odpovědět
23.4.2018 22:15
Avatar
Radka Jánská:23.4.2018 22:18

A jeste jeden dotaz ... neporusujeme pouzitim modifikatoru protected u atributu zapouzdreni? V kapitole o getterech a setterech se az na vyjimky doporucuje pouzivat u atributu modifikator private. Je tohle ta vyjimka? Jak ochranim atributy pred zmenou zvenci? Zase diky.

 
Odpovědět
23.4.2018 22:18
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Radka Jánská
David Čápka:23.4.2018 22:32

Protected to právě nevystavuje zvenčí, ale jen pro potomky, to je pořád zevnitř.

Odpovědět
23.4.2018 22:32
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Radka Jánská:24.4.2018 18:56

V predchozi kapitole pises, ze protected zpristupnuje atributy vsem tridam v balicku a potomkum v jinych balickach ... takze pokud mam metodu main, tak musi byt v jinem balicku? Kolik miva takovy prumerny program balicku?

 
Odpovědět
24.4.2018 18:56
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Radka Jánská
David Čápka:24.4.2018 19:07

Máš pravdu, moje chyba, Java má tohle dost nešikovně nastavené. Pokud bys chtěla atributy nebo metody zpřístupnit pouze potomkům, nepíše se před ně žádný modifikátor přístupu. Je to potom něco mezi private a protected. Doplním to tam.

Odpovědět
24.4.2018 19:07
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Odpovídá na David Čápka
Radka Jánská:24.4.2018 22:13

Dekuju za vysvetleni. Je toho hodne, zvlast na zacatecnika jako ja, je jasne, ze zadne materialy nemuzou obsahovat vsechny informace... Moc ocenuju tvou rychlou odpoved.

 
Odpovědět
24.4.2018 22:13
Avatar
patrik.hrnciar:5.5.2018 13:34

Ahoj, v metode grafickyUkazatel v casti :
if ((pocet == 0) && (nazivu())) {
pocet = 1;
}
v pripade Maga bude v ukazovateli many vzdy minimalne 1 dielik aj ked bude mana = 0 , a mag bude nazive.

 
Odpovědět
5.5.2018 13:34
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:12.7.2018 9:58

O potomků je nutné vždy volat konstruktor předka. Je to z toho důvodu, že bez volání konstruktoru nemusí být instance správně inicializovaná. Konstruktor předka nevoláme pouze v případě, že žádný nemá. Náš konstruktor musí mít samozřejmě všechny parametry potřebné pro předka plus ty nové, co má navíc potomek. Některé potom předáme předkovi a některé si zpracujeme sami. Konstruktor předka se vykoná před naším konstruktorem.

To není úplně tak pravda.
Pokud voláš konstruktor předka, tak ten se inicializuje vždy "správně":)
Logika dědičnosti a proč se musí volat konstruktor předka spočívá v tom, že i když to tak nevypadá, tak my když voláme jakéhokoliv potomka, tak JVM v pozadí vytvoří i instance všech předků, ze kterých potom voláme překryté nebo zděděné metody tak, že my sice nevidíme, že to volá předek, ale je to tak.

V podstatě tato rekurze vytváření instancí na pozadí končí až u kořenové třídy všech tříd - Objektu.
Příklad: Vytvořím si třídu A a B. Třída B bude dědit z A. Jenže (a to si moc lidí hned tak neuvědomí) i třída A dědí. A dědí z Object class. (Object třída je jediná třída, která nedědí od nikoho).
Takže My můžeme vytvořit třeba i bezparametrický konstruktor u tříd A a B a následně vytvoříme novou instanci třídy B. JVM ovšem na pozadí vytvoří nejdřív novou instanci Object, potom novou instanci A a až potom instanci B.
A u parametrických tříd je to úplně to samé. Vždy volám aspoň jeden z konstruktorů předka - právě aby se vůbec mohlo z něčeho dědit.
U implicitních konstruktorů je jediná výjimka, protože ty jsou defaultně skryté, takže je není třeba definovat. Kdyby to tak nebylo, tak i když bychom si vytvořili úplně novou samostatnou třídu, tak bychom museli vždy psát:

public class newClass extends Object {
        public newClass() {
                super(); // <---- odkazuje (dědí) ze třídy Object a proto je třeba vytvořit bezparametrický konstruktor. Object jiný nemá
        }
}
Editováno 12.7.2018 9:59
Odpovědět
12.7.2018 9:58
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Jiří Satora:30.12.2018 12:17

Na mě je to moc složité. Ani jsem to nepřečetl celé. :-###

 
Odpovědět
30.12.2018 12:17
Avatar
Jozef Tomašec:18.2.2019 21:11

Popravde som sa v tej dedičnosti trocha stratil. Možno, keby bol priklad pisany rovno od zaciatku, ale pri tom prepisovani jednotlivych prikazov mi to prišlo komplikovanejšie.

 
Odpovědět
18.2.2019 21:11
Avatar
Odpovídá na patrik.hrnciar
Karel Stehlík:26.7.2019 20:02

Tak si tu podmínku v metodě "grafickyUkazatel" ve třídě "Bojovnik" změň takto:

if ((pocet == 0) && (nazivu()) && (aktualni != 0))

Když to v podmínce projde až k tomu parametru metody "aktualni", je jasné, že v případě hodnoty 0 musí jít o manu, jinak by se podmínka ukončila už při testování metody "nazivu()", která by v případě nulového života byla false.

 
Odpovědět
26.7.2019 20:02
Avatar
Michal Richter:13.9.2019 14:18

Chybička v textu, místo Arena.java má být Program.java:
"Přesuňme se nyní do Program.java a druhého bojovníka (Shadow) změňme na mága, např. takto:"

 
Odpovědět
13.9.2019 14:18
Avatar
Gemy
Člen
Avatar
Gemy:24. května 17:07

Nějaké vysvětlení prosím pro formát(%1$-) ?

Odpovědět
24. května 17:07
Peníze neznamenají úspěch.
Avatar
Gemy
Člen
Avatar
Odpovídá na Gemy
Gemy:24. května 18:15

Už jsem pochopil format() ... bože to je těžká bodel :-D

String s = "X";
System.out.printf("%-"+(s.length()+1)+"s&%<"+(s.length()+1)+"s\n", s);
Odpovědět
24. května 18:15
Peníze neznamenají úspěch.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 64 zpráv z 64.