« 1 2 3 »
Autor Zpráva
tiso
Profil
smiesek: Tak inak. Máš triedu Dog:
class Dog
{
    private $name;
    
    function __construct($name)
    {
        $this->name = $name;
    }
    
    public function bark()
    {
        echo 'Haf!';
    }
Napíš program, ktorý vytvorí psa s menom Goro a 2x zaštekaj.
smiesek
Profil
tiso:
$pes = new Dog('Goro');
$pes->bark();
echo '<br />';
$pes->bark();

Koukni prosím.
tiso
Profil
smiesek: si šikovná. Vieš použiť cudziu triedu. To je to, čo často programátori robia - použijú už hotovú triedu. Nemusia ju programovať.
Druhá uloha: sprav také úpravy triedy a programu, aby si vypísala meno psa, ale v tvare 'Goro, the dog'.
smiesek
Profil
tiso:
class Dog
{
    private $name;

    function __construct($name)
    {
    $this->name = $name;
    }

    public function kdoJe($name)
    {
    echo $this->name,' , the dog';
    }
}

$pes = new Dog('Goro');
$pes->kdoJe($pes);

Ale tady se asi spíše podle toho všeho co se mi snažíte vysvětlit tak:
a) jelikož datový člen $name je private, použiju přístup pouze zevnitř pomocí $this = OK
b) ALE už nepoužívám getter a setter, což v tomto případě nemůžu kontrolovat, jestli třeba nebyla vložena číselná hodnota = ERROR

Takže to že mi to výše uvedené funguje je spíše zázrak a pro private a protected datové členy se to takhle nedoporučuje použít? Spíše to upravit na použití get a set?
Dan Charousek
Profil
smiesek:
Ta metoda kdoJe() nepotřebuje přijímat žádný parametr. Když se podíváš pozorně, tak v jejím těle:
    public function kdoJe($name)
    {
    echo $this->name,' , the dog';
    }
parametr $name, ve kterém předáváš instanci toho objektu (zcela zbytečně, protože metodu kdoJe() voláš na instanci $pes, takže v ní pak můžeš přistupovat k private atributům), vůbec nepoužíváš. Mimo to, proměnné a řetězce (viz. řádek 12 tvého kódu) bys měla spojovat přes tečku. Správně by ta metoda měla vypadat takto:
    public function kdoJe()
    {
    echo $this->name . ' , the dog';
    }
tiso
Profil
smiesek: super (až na ten zbytočný parameter, ako napísal Dan Charousek). Takže vieš zmeniť existujúcu triedu i program, aby robili to čo chceš. Postupuješ po malých krôčikoch vpred.

Keďže je premenná private, tak si správne vytvorila novú metódu, ktorá k nej vie pristupovať a zvonku triedy si ju zavolala. Takto sa to bežne robí.
b) použiť getter by bola druhá možnosť ako to urobiť. Vyzeralo by to takto:
class Dog
{
    private $name;
 
    function __construct($name)
    {
    $this->name = $name;
    }
 
    public function getName()
    {
        return $this->name;
    }
}
 
$pes = new Dog('Goro');
echo $pes->getName() . ' , the Dog';



smiesek: pochopila si ten môj príklad s getterom? Je ti ešte niečo nejasné? Ako si na tom s angličtinou?
smiesek
Profil
Dan Charousek:
beru na vědomí, s tou proměnnou se budu pozorně zaměřovat, co se týká spojení řetězce, ano pravda, je mi zřejmé, že se spojuje pomocí tečky, ale při prvních pokusech mi to vypisovalo chybu, nyní již při použití tečky samozřejmě nikoliv, tak jsem někde byla nepozorná.

tiso:
v jakém případě tedy a nebo kdy používat přístup přímý a nebo nepřímý (getter a setter)?
Pochopila jsem správně z předchozí strany, že pokud nepotřebuju nic kontrolovat, tedy set(kontrola - třeba podmínka aby bylo číslo) a get(provádět - třeba nějaký výpočet) tak mohu použít i variantu A) prvně tedy mnou vytvořené? Ale zase to lze použít pouze u private a protected, ale nikoliv u public?


tiso:
děkuju, tvou úpravu jako druhou možnost použití jsem pochopila a taky koukám na další možný způsob výpisu textu za datovým členem.

Bohužel nemohu moc vycházet z angličtiny, protože jsem si ji tehdy nedala jako hlavní jazyk - tehdy jsem se nezajímala ani o internet, tvorbu stránek a už vůbec ne programování, což mi došlo až postupem času, že bych na tom byla jinak, když většina dokumentace je v angličtině, ale ani už nedokážu to dohnat :(
Koukala jsem se i na nějaký videa na YT třeba právě na ty Třídy, ale snažila jsem se tedy spíše hlavně pochytit co vidím, než co se mluví, když tomu nerozumím, ale to je špatně, protože co vidím = fotografická paměť mi je v tomto případě k ničemu, stačí malá změna a jsem úplně ztracená.
juriad
Profil
smiesek:
getter a setter můžeš používat bez ohledu na modifikátor přístupu (private/protected/public). Jsou to dvě odlišné věci.
Pokud programuješ pro sebe, je jedno, co použiješ. Pokud tvoříš něco určené pro jiné programátory, měla bys přemýšlet, jak chceš, aby tvé třídy používali. Chce to zkušenost, mít cit, pro to určit, jak se tvůj kód bude do budoucna rozšířovat a měnit (to je hlavní důvod).

Představ si, že máš napřed napsat dokumetaci ve stylu php.net/manual/en/class.datetime.php (tedy deklarace veřejných metod, veřejné proměnné a konstanty). A až to budeš mít hotové, tak to naprogramuješ a nikdy nebudeš smět deklaraci metody ani proměnné změnit. Budeš moci jen přidát nové metody, nové parametry a nové proměnné. Můžeš si ale vesele používat privátní a protected proměnné a metody, ty totiž součástí rozhraní nejsou.
Když začneš přemýšlet tímto způsobem, tak se do jisté míry odprostíš od samotné implementace (tu zvládne každý programátor) a přesuneš se do návrhu rozhraní (jak budou ostatní používat tvůj kód).
Dan Charousek
Profil
smiesek:
Neexistují pevně daná pravidla, kdy settery a gettery používat. Většinou se používají, když předpokládáš, že tvoje třídy bude používat i někdo jiný - aby uvnitř třídy nenastala nějaká nečekaná situace. Všeobecně platí, že třída by měla být co nejvíc blbůmvzdorná. Podívej se na následující příklady, ve kterých vytvářím instanci objektu pes a nastavuji jméno:

<?php
class Pes {

    public $name;

}

$alik = new Pes();
$alik->name = "Alíček";
echo "Můj pejsek je " . $alik->name;

Atribut $name je public, to znamená, že ho můžu měnit a přistupovat k němu zvenku třídy - ($alik->name).
Sice vše funguje, ale není to optimální způsob. Člověk/Programátor, který tuto třídu obsluhuje má příliš velkou volnost. Nikde se neověřuje, co se do atributu $name ukládá. Klidně bych do něj mohl vložit pole a nikomu by to nevadilo.

Další možností je neměnné atributy třídy, jako například jméno, rasu (hodnoty, u kterých předpokládáme, že se v průběhu nebudou měnit) nastavovat při vytvoření instance objektu - pomocí metody __construct()

<?php
class Pes {

    private $name; # jméno
    private $race; # rasa

    public function __construct(string $name,string $race) {
        $this->name = $name;
        $this->race = $race;
    }

    public function getName() {
        return $this->name;
    }

    public function getRace() {
        return $this->race;
    }

}

$alik = new Pes("Alíček", "Německý ovčák");
echo "Můj " . $alik->getName() . " je " . $alik->getRace();

Všimni si zvýrazněných částí v konstruktoru, ty zajistí, že parametry předávané při vytváření instance objektu Pes (na řádku 21) budou datového typu řetězec (string). Pokud potřebuješ specifičtější kontrolu, můžeš hodnoty kontrolovat pomocí podmínek, např. pokud nastavuješ věk a nechceš, aby někdo uvedl záporné číslo: if($vek < 0) {#chyba}, atd...
V tomto případě jsou již atributy třídy označené jako private, tzn., že k nim mohou přistupovat jen metody dané třídy. Nastavování hodnot zajišťuje konstruktor a čtení hodnot zajišťují getName() a getRace() metody (takzvané gettery).

Třetí možností je mít i speciální metody na nastavování hodnot (settery), ty se používají většinou u atributů, u kterých můžeme očekávat, že se jejich hodnota může měnit.

<?php

class Pes {

    private $name;
    private $race;
    private $color;

    public function __construct() {string $name, string $race} {
        $this->name = $name;
        $this->race = $race;
    }

    public function setColor(string $color) {
        $this->color = $color;
    }

    public function getName() {
        return $this->name;
    }

    public function getRace() {
        return $this->race;
    }

    public function getColor() {
        return $this->color;
    }

}

$alik = new Pes("Alíček", "Německý ovčák");
$alik->setColor("hnědá");

echo "Můj " . $alik->getName() . " je " . $alik->getRace();
echo "Barva jeho kožichu je " . $alik->getColor();

// necháme Alíka obarvit
$alik->setColor("černá");

echo "Po obarvení je barva Alíkovo kožichu " . $alik->getColor();

?>
Keeehi
Profil
Dan Charousek:
Všimni si zvýrazněných částí v konstruktoru, ty zajistí, že parametry předávané při vytváření instance objektu Pes (na řádku 21) budou datového typu řetězec (string).
Je důležité říct, že pro string, bool, int a float to funguje až od PHP verze 7. Od 5.0 si takto jde vynutit pouze třídu (class) a rozhraní (interface). V 5.1 bylo přidané pole (array) a v 5.4 něco, či jde volat > funkce (callable)
Viz php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
Dan Charousek
Profil
Keeehi:
Děkuji za doplnění.
tiso
Profil
smiesek: tými riešeniami úloh si dokázala, že vieš pracovať s triedami. To je základ, na ktorom môžeš stavať. Celá teória ťa mätie a vyvoláva viac otázok ako odpovedí, musíš postupovať postupne:
1. potrebujem toto - viem to spraviť takto
2. neviem ako to spravíť - doštudujem/spýtam sa

Kedy používať priamy a nepriamy prístup? Podľa toho, ako chceš aby sa trieda používala a zároveň, aby si zabránila nesprávnemu použitiu.


K viditeľnosti ešte raz: máš rôzne spôsoby prístupu k premenným triedy (zvnútra/zvonku/z potomka, priamy/nepriamy), viditeľnosť určuje ktoré sa dajú použiť a ktoré nie. Keď máš niečo public, tak k tomu môžeš pristupovať všetkými spôsobmi. Potrebuješ pristupovať k private premennej? Možností je menej.
smiesek
Profil
:(

tak asi tedy nyní takhle ještě:
Postup pro práci s třídami a moje neustále hledání otázek co mi není jasné je následující:

1. vytvořím název třídy
2. ve třídě si určím datové členy, ke kterým určím zapouzdření - public/private/protected
dle zapouzdření musím dodržet zdali budu přistupovat zvenku/zevnitř
3. rozhodnu se, jakým způsobem bude přistupovat k proměnným datovým členům - přímo/nepřímo
pokud se rozhodnu přistupovat pouze přímo, hrozí ovlivnění vstupních hodnot proměnných programátorem a nezabráním nesprávnému používání
4. napíšu patřičné operace pro výpis hodnot pomocí třídy
tiso
Profil
smiesek: Daj nejaký príklad úlohy čo chceš reálne spraviť.
smiesek
Profil
tiso:
já nemám konkrétní příklad, pořád se nějak snažím pochopit celou tu problematiku, tedy postup je špatně?
Dan Charousek
Profil
smiesek:
Nemá cenu se to snažit učit obecně, když ti to dělá potíže. Jak jsem psal ve svém příspěvku výše, různé problémy vyžadují různá řešení.
tiso
Profil
smiesek: viac by ti mal vyhovovať prístup, ktorý tiež používam:
1. viem čo chcem urobiť
2. napíšem si riešenie pomocou volaní metód tried = definujem názvy tried a ich vonkajšie rozhranie
3. vyplním vnútro tried (premenné, metódy, základnú viditeľnosť)
4. poupratujem - odstránim duplicity, preskúmam viditeľnosť

Konkrétny príklad som chcel preto, aby som ti to názorne ukázal.
juriad
Profil
smiesek:
Vezmi si nějakou úlohu a tu zkus vyřešit.

S čím si jde dost vyhrát, je tvorba formulářů. Podívej se na stránku doc.nette.org/en/2.3/forms a zkus si něco podobného vytvořit.
Třídu Form, která bud mít metody addXYZ pro jednotlivé typy políček.
Navrhni si nějaké použití; například přihlašovací formulář bude vypadat takto:
$form = new Form('login.php', Form::POST);
$fs1 = $form->addFieldSet('jmeno a heslo');
$tf1 = $fs1->addTextField('name', 'Jméno');
$tf1->setTitle('Sem zadejte své jméno');
$tf2 = $fs1->addPassword('pass', 'Heslo');
$cb = $form->addCheckBox('permanent', 'Zapamatovat přihlášení');
$cb->setChecked(true);
$form->addSubmit('login', 'Přihlásit');
echo $form;

Zpočátku se nemusíš starat o to, aby byl kód pěkný, jaké používat modifikátory atp. Prostě si definuj, jak by se ti to líbilo používat, a to potom naprogramuj. A časem zjistíš, že to jde lépe. Až budeš mít první funkční verzi, nech nás ji zhodnotit.
smiesek
Profil
dobře, já vím, že nic obecně, přece jsem to i zmiňovala, že potřebuju vždy názorný příklad, než pouhé fotoukázky, tak jsem si chtěla/šla nejprve alespoň něco přečíst o Třídách a pak bych se ráda pokusila nějaké hotové řešení převést za pomocí těch Tříd, popř. jestli bych pak dokázala vymyslet nějaké vlastní.

Mě třídy příjdou jako vlastní funkce, kterým pak jen nadatluju proměnné a výsledek by měl být na světě, nebo to spočívá v něčem jiném jejich použití? S tím tedy, že souvisí s OOP? Nebo už jejich používáním se mluví o OOP?

tiso:
vnější rozhraní tříd myslíš pak už jen následné předávání těch proměnných?

Co jsi napsal jsem pochopila v následující postup
class Dog
{
    private $name;
    
    function __construct($name)
    {
        $this->name = $name;
    }
    
    public function bark()
    {
        echo 'Haf!';
    }

2. definice názvu třídy = Dog

3. vnější rozhraní = viz kod níže
$pes = new Dog('Goro');
$pes->bark();
echo '<br />';
$pes->bark();

4. proměnné = $name

5. funkce = bark()

6. základní viditelnost = private

O takovou představivost postupu mi jde.
tiso
Profil
smiesek: podľa mojho postupu by to bolo:
1. chcem program, ktorý vytvorí psa s menom Goro a 2x zašteká
2. volal by som asi nejak takto:
$pes = new Dog('Goro');
$pes->bark(2);
takže trieda sa bude volať Dog, bude mať nejakú metódu bark a bude mať nejakú premennú na uloženie mena
3. napísanie triedy
class Dog
{
    private $name;
    
    function __construct($name)
    {
        $this->name = $name;
    }
    
    public function bark($times = 1)
    {
        while ($times > 0) {
            echo 'Haf!';
            $times--;
        }
    }
}
4. nie sú tam žiade duplicity, ale zistil som, že to meno psa nikde nepoužívam, tak sa môžem rozhodnúť že ho z triedy zmažem
Dan Charousek
Profil
tiso:
V metodě bark() by bylo vhodnější využít for cyklus. Jednak známe celkový počet iterací a druhak není dobré přepisovat hodnotu parametru metody. Co když bychom chtěli na konci metody vypsat: echo $this->name . " zaštěkal " . $times . "x";
smiesek
Profil
dobře, děkuju, tak poprosím, nejprve na nějakých jednoduchých příkladech, vím, že tu nejste od toho, abyste někoho vodili za ručičku, ale od hodnocení a rady konkrétních problému, jestli mi můžete dát nějaký úkol, tak jako mi dal tiso, který bych se snažila průběžně řešit a komentovat a ptám se, co by mi nebylo jasné, proč se do nemůže udělat tak či onak a naopak.

Mám představu o těch formulářích, vím, jak je napsat v html s použitím php, ale pro začátek by mi to přišlo až moc složité - co dal výše juriad moc nepobírám, tak raději začít něčím jednodušším a pak se případně pokusit převést ty složité formuláře.

děkuju jestli je to z vaší strany možné mi takhle pomoci, jinak si nevím rady :(
juriad
Profil
smiesek:
Objekty mají obvykle význam k tomu, abys něco namodelovala (jako třeba ten formulář) a pak ho najednou vytvořila. Vytvořit psa sice vypadá pěkně jako příklad, ale není zřejmé, k čemu je to vše dobré.

Kdybys chtěla dělat ty formuláře bez objektů, buď bys rovnou volala funkce:
startForm(...)
startFieldSet(...)
showTextField(..., ..., ..., ...) # mnohem více paramerů, protože musíš počítat se vším (na rozdíl od setterů, které stačí zavolat později)
showPassword(..., ..., ...)
endFiledSet()
showCheckBox(...)
showSubmit(...)
endForm()

Nebo by sis možná vytvoříla nějaké pole:
array('type' => 'form', action => '...', method => 'POST',
  array('type' => 'fieldset', 'legend' => 'jmeno a heslo',
    array('type' => 'textfield', 'name' => 'name', 'comment' => 'Jméno', 'title' => 'Zadejte jméno'),
    array('type' => 'password', 'name' => 'pass', 'comment' => 'Heslo')
  ),
  array('type' => 'checkbox', 'name' => 'persistent', 'comment' => 'Zapamatovat', 'checked' => 'checked'),
  array('type' => 'submit', 'name' => 'login', 'comment' => 'Přihlásit')
);
A pak bys měla nějakou funkci, která by dostala toto pole a vypsala formuláš jako HTML.

A další krok je zbavit se polí, kde vše musíš vypisovat ručeně a překlep nezpůsobí okamžitou chybu.

Programování s objekty se jakové deklarativnější (popisuješ co chceš, aby bylo) a ony se o to nějak vnitřně postarají (a tobě je jedno jak).
Dan Charousek
Profil
Zkus naprogramovat hrací kostku. Při vytvoření instance nastavíš, kolik má stěn, a metodu hoď, která vrátí náhodné číslo od 1 do "počet stěn"

$sestistenna_kostka = new Kostka(6);
echo $sestistenna_kostka->hodSi(); // vygeneruej náhodné číslo
echo $sestistenna_kostka->hodSi(3); // vygeneruje 3 náhodné čísla . hodí třikrát
smiesek
Profil
juriad:
to byl pouze příklad s tím psem, je mi jasné, že nepoužitelné do reálu, tak tedy něco, co by se využilo u základních stránek
lionel messi
Profil
smiesek:
juriad:
to byl pouze příklad s tím psem, je mi jasné, že nepoužitelné do reálu, tak tedy něco, co by se využilo u základních stránek

Príklad [#24] by sa ale už celkom hodiť mohol.
smiesek
Profil
tak nějak vůbec netuším, neumím si to prostě představit :(

class Kostka {

    private $cislo;

    public function hodSi() {
        return $this->cislo = rand(0,999);
    }
}

vlastně je to pak těžko, když netuším jak by se to naprogramovalo ani v PDO


nebo takhle nějak?
Vůbec netuším co dělám a jdu pokus/omyl a třeba se trefím :(
class Kostka {

    private $cislo;

    public function __construct($cislo) {
        $this->cislo = $cislo;
    }

    public function hodSi() {
        return rand(0,999);
    }
}
lionel messi
Profil
smiesek:
Skôr takto:

class Kostka {

  private $pocetSten; //správne ste sa rozhodli nechať atribút privátny, ale pomenovanie cislo v tomto prípade nebolo najlepšie, nehovorilo, aké číslo reprezentuje
  
  public function __construct($pocetSten) { //konštruktor ste na druhý pokus vytvorili správne
    $this->pocetSten = $pocetSten;
  }
  
  public function hodSi($pokus = 1) {
    if ($pokus >= 1) {
      for ($i = 0; $i < $pokus; $i++) {
        return rand(1, $this->pocetSten); //vrátime náhodné číslo pre každý z pokusov
      }
    }
    
    //tu by som ešte zavolal výnimku pre prípad, že by sa ktosi snažil hodiť záporný počet pokusov, ale tým sa zatiaľ vôbec nezaoberajte
    
  }
}

Ako začiatočník s OOP taktiež privítam prípadné kritické postrehy k môjmu kódu.

Pri volaní rand() pozor na to, že potrebujete iba číslo, ktoré reálne môže na kocke byť - vo vašom prípade od 1 po počet stien, vy ste generovali čísla od 0 do 999, čo je v tomto prípade nezmysel.

Na prípadné nejasnosti sa pokojne pýtajte.
Jan Tvrdík
Profil
lionel messi:
Ako začiatočník s OOP taktiež privítam prípadné kritické postrehy k môjmu kódu.
Ten for cyklus nedává smysl, když po první iteraci metodu returnem opustíš.
lionel messi
Profil
Jan Tvrdík:
lionel messi:
„Ako začiatočník s OOP taktiež privítam prípadné kritické postrehy k môjmu kódu.“
Ten for cyklus nedává smysl, když po první iteraci metodu returnem opustíš.

V tom prípade by som na to išiel zhruba takto:

public function hodSi($pokus = 1) {
    $vysledok = "";
    if ($pokus >= 1) {
      for ($i = 0; $i < $pokus; $i++) {
        $vysledok .= rand(1, $this->pocetSten);
      }
      return $vysledok;
    }
    
    //tu by som ešte zavolal výnimku pre prípad, že by sa ktosi snažil hodiť záporný počet pokusov, ale tým sa zatiaľ vôbec nezaoberajte
    
  }

Alternatívou (zrejme lepšou) tiež môže byť naskladať jednotlivé výsledky hodov do poľa.

Return presunutý na zodpovedajúce miesto.
« 1 2 3 »

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: