Autor | Zpráva | ||
---|---|---|---|
tiso Profil |
#1 · Zasláno: 19. 8. 2015, 10:30:15
smiesek: Tak inak. Máš triedu Dog:
class Dog { private $name; function __construct($name) { $this->name = $name; } public function bark() { echo 'Haf!'; } |
||
smiesek Profil |
tiso:
$pes = new Dog('Goro'); $pes->bark(); echo '<br />'; $pes->bark(); Koukni prosím. |
||
tiso Profil |
#3 · Zasláno: 19. 8. 2015, 10:52:04
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 |
#5 · Zasláno: 19. 8. 2015, 11:15:18
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'; } $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 |
#9 · Zasláno: 19. 8. 2015, 11:56:26
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 |
#10 · Zasláno: 19. 8. 2015, 12:25:05
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 |
#11 · Zasláno: 19. 8. 2015, 12:30:25
Keeehi:
Děkuji za doplnění. |
||
tiso Profil |
#12 · Zasláno: 19. 8. 2015, 12:55:47
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 |
#14 · Zasláno: 19. 8. 2015, 14:52:53
smiesek: Daj nejaký príklad úlohy čo chceš reálne spraviť.
|
||
smiesek Profil |
#15 · Zasláno: 19. 8. 2015, 14:55:10
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 |
#16 · Zasláno: 19. 8. 2015, 14:59:28
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 |
#17 · Zasláno: 19. 8. 2015, 15:04:30
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 |
#18 · Zasláno: 19. 8. 2015, 15:16:17
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 |
#19 · Zasláno: 19. 8. 2015, 15:16:28
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); 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--; } } } |
||
Dan Charousek Profil |
#21 · Zasláno: 19. 8. 2015, 15:35:43
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 |
#23 · Zasláno: 19. 8. 2015, 15:47:52
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 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 |
#24 · Zasláno: 19. 8. 2015, 16:01:05
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 |
#25 · Zasláno: 19. 8. 2015, 16:01:49
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 |
#26 · Zasláno: 19. 8. 2015, 16:02:57
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 |
#29 · Zasláno: 19. 8. 2015, 20:27:38
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. |
||
Téma pokračuje na další straně.
|
0