Autor Zpráva
G3n3sis19
Profil
Zdravím.

Často slíchávám o tom, že by se nemělo povolovat dostávat se k citlivým proměnným v classe, ale měly by se udělat pro ně tzv. gettery a settery. Do teď nechápu, proč.
class ApiBase {
    private static $accessToken;
    function siteSelect($siteName) {
         return new Api($siteName);
    }

    function getAccessToken() {
        return self::$accessToken;
    }
}

abstract class Api {
    function __construct($siteName) {
        $this->accessToken = ApiBase::getAccessToken();
    }
}
proč je to takhle komplikovaný? Co za tím je?

Napadlo mě, aha, tak je to proto, aby se do toho nezasahovalo. (Nedovolilo to změnu accessTokenu). Ale tím si nejsem jistý

Tak jak to je?

EDIT: tady je přesná ukázka toho, kde mi příjde úplně nesmyslné. No řekněte mi, proč (první odpověď).
avšak tadyta odpověď odvrací tu první


Asi jsem našel svojí odpověď: http://stackoverflow.com/a/3644343/1044146
Ugo
Profil
Faktem je, že žádnej praktickej přínos to nemá, ani z hlediska bezpečnosti, ani čitelnosti ani rychlosti nebo prevence chyb. Někde jsem slyšel že to kopíruje reálnej svět, to je samozřejmě ještě větší blábol. Je to jako moje milovaná funkce v zendu (nebudu jí teď hledat, nevím už kde) která má nějakých 15 znaků název a tělo obsahuje jen.. return "'";. Gettery a settery jsou pomalejší a brání volnosti.

Z druhé strany barikády - hodně často je třeba dělat víc věcí než jen $this->x=$x a často to ani není dopředu jasné, když máš setter a rozhodneš se připsat funkčnost (např. vstupní hodnota může být nově objekt, který převedeš na int) tak není třeba měnit aplikaci, u getteru je to trošku jiný, tam tahle potřeba neni. Set metody taky umožnují fluent zápis, takže tunu zbytečnejch řádků dáš na jeden stejně přehednej. A poslední věc, mraky programátorů se snaží své nástupce nebo uživatele chránit před sebou samým s chybným předpokladem že kód bude hezčí a funkčnější. Naopak je méně ohebný, je třeba ho déle studovat a nutí používat jiné způsoby ež na který je uživatel zvyklý, ale to je jiné téma.

Za sebe vidím tuhle historku typu "jedna baba povidala" jako nepřínosnou ve formátu bez úpravy I/O dat, ale zároveň si myslím ... dát obě možnosti a ničemu nebránit
G3n3sis19
Profil
Ugo:
jasně, pochopím, když se gettery a settery použijí v případě, že gettery kontrolují/převádějí a settery jen nesetujou ale i kontrolujou/validujou/setujou i jiný (aliasy)
_es
Profil
Ugo:
Faktem je, že žádnej praktickej přínos to nemá, ani z hlediska bezpečnosti, ani čitelnosti ani rychlosti nebo prevence chyb.
No ale podľa druhého odseku to má význam pre budúce úpravy kódu.
David Grudl
Profil
Drobnou výhodou při přístupu přes getter/setter je, že nelze udělat unset($obj->property), naopak to komplikuje život, pokud je v $obj->property uložené pole, které chceme modifikovat.
joe
Profil
David Grudl:
naopak to komplikuje život, pokud je v $obj->property uložené pole, které chceme modifikovat.

To jde udělat přes referenci, ne? public function &getPole() { return $this->pole; }
Joker
Profil
G3n3sis19:
V PHP to má smysl spíš teoreticky, resp. pro „objektové fundamentalisty“ (ale proč by objektový fundamentalista programoval v PHP?)

Pokud jde o tu teorii, jeden z principů objektově orientovaného programování je princip otevřenosti a uzavřenosti: Třída má být otevřená pro rozšíření funkčnosti, ale uzavřená pro změny kódu (ještě jinak: Funkčnost třídy by mělo být možné co nejvíce rozšířit, ale přitom se nesmí sáhnout do zdrojáku samotné třídy).
Při důsledném uplatnění tohohle principu by všechny atributy měly být schované za gettery a settery, protože zveřejnění atributu omezuje rozšiřitelnost třídy.
Nox
Profil
Ugo:
Někde jsem slyšel že to kopíruje reálnej svět
To jsi nějak přeslechl, protože toto se traduje o OOP, ne o g/setterech.

snaží své nástupce nebo uživatele chránit před sebou samým s chybným předpokladem že kód bude hezčí a funkčnější
Když se snažím mít aplikaci solidní a mít ověřené vstupy atd., tak to znamená, že to bude méně funkční?

getteru je to trošku jiný, tam tahle potřeba neni.
Není pravda ... v getteru mohou být různá oveření, transformace výstupu, lazy loading etc. etc.

joe:
Ne úplně ... tedy ... až do verze 5.4, teď už máme array dereferencing



----> Gettery a Settery jsou správná věc. Jediný problém je jejich implementace v PHP. Manuálně datlovat g/settery je na hlavu. Existuje __call (případně ještě __get/__set), jenomže to je bohužel pomalejší a IDE nebude automaticky napovídat (takže by se stejně muselo generovat).

Momentálně není v PHP k dispozici dokonalé řešení.

Třeba v C# je toto bez problému, uživatel si napíše jen ty g/settery, kde je nějaká logika, zbytek je automaticky. A vůbec to tam mají takové vychytanější.
Mastodont
Profil
Z praktického hlediska setter i getter umožňuje provádět nějaký kód při čtení/zápisu vlastnosti. Například pro kontrolu toho, co chceš přiřadit.

(Nox byl o 20 sekund rychlejší..)
Ugo
Profil
Nox:
To jsi nějak přeslechl, protože toto se traduje o OOP, ne o g/setterech.
Toto jsem opravdu měl možnost číst, tedy ne konkrétně toto, ale to že ve světě neexistují public věci (? :D) a tak je nutné používat get/set , čili chápu tak že to má simulovat real.

Ověřené vstupy mít můžeš aniž by to znefunkčnilo app, tak trochu nepochopení věty. Tím že máš funkci setVar() a zakážeš přidání $var napřímo nic nezískáš, jen odhodíš kus svobody používání a někdy se to může hodit nastavovat věci ručně, protože fce set ti nemusí něco bezdůvodně dovolit, něco ti může oříznout atp. třeba z důvodu že to tak 99x potřebuješ, ale jednou chceš něco jinak a máš po ptákách, musíš upravovat třídu, přidávat hafec podmínek, parametrů nebo funkci jen proto že to 1x potřebuješ jinak.

To s tím getterem jsem asi nenapsal jasně, samozřejmě tam chybí slůvko většinou (tedy není potřeba, dává to v kontextu smysl - u setterů je potřeba často měnit, u getteru není potřeba často měnit)

funkce __call()/__get()/__set() není (může být částečně) zastoupením, u setVar mám jiné požadavky než u setRav, proto ty funkce píši, jinak je vynechám a nic se nestane, takže co jsi zapomněl dodat, že magické metody mají tak trochu jiný význam.

celé mi to připadá jako kvóty pro ženy ve vedení nebo rovnost okurek, zakázání žárovek atd. atd. já chci ale jíst křivou okurku s mužským šéfem pod wolframovým vláknem hned vedle nastartovaného trabanta
_es
Profil
Ugo:
ím že máš funkci setVar() a zakážeš přidání $var napřímo nic nezískáš, jen odhodíš kus svobody používání a někdy se to může hodit nastavovat věci ručně, protože fce set ti nemusí něco bezdůvodně dovolit, něco ti může oříznout atp.
Presne pre tieto dôvody to je prospešné z hľadiska budúcich úprav kódu. Ak niekto napíše knižnicu a niekto iný ju používa „inak“. Trochu iné je, ak je autor knižnice aj používateľ len jedna osoba.
Ugo
Profil
_es:
souhlasím že to je prospěšné (respektive většinou nutné), mě se jen nelíbí to blokování jiných možností, prostě nejsem člověk co bude žalovat výrobce za to že sem v mikrovlnce zabil kočku, ale nikdo mi nebrání tu mikrovlnku použít pro sušení zvířat, jen když to nebude fungovat tak je to moje chyba
_es
Profil
Ugo:
mě se jen nelíbí to blokování jiných možností
Ktoré by po použití novšej verzie knižnice nemuseli fungovať.
Ugo
Profil
_es:
Ktoré by po použití novšej verzie knižnice nemuseli fungovať.
Ano (moje chyba)
Nox
Profil
Ugo:
Kdyby sis zkusil delší dobu používat nějaký kód třetí strany, myslim že bys pochopil.

Navíc ... z "nějakého" důvodu je používají i zkušení programátoři, z "nějakého" důvodu to autoři přímo zakomponovali do C#, do nové verze JS atd.

Zakázáním ->var skoro nic neztratíš. Při použití ->var ztrácíš kontrolu (leda __set), místo ověření vstupů hned u zdroje změny musíš rozkopírovat ověření obsahu do všech částí kódu, kde s tím manipuluješ - porušení DRY, porušení Fail fast. To poslední je v netriviálním kódu nepříjemnější, než se zdá.
Navíc g/settery imho jasněji definují rozhraní, prostě vím, co si s tím kódem můžu dovolit.
Plus, jak píše _es, autor kódu má možnost úpravy chování, aniž by to rozbilo ostatním kódy.

u setVar mám jiné požadavky než u setRav
Jediné dva problémy jsou typehinting (typehint array/Classname) a to, že IDE bude napovídat jen přes @method ... pro ty metody suplované magickou metodou.

Ty, kde máš speciální požadavky, si přece můžeš napsat ručně.

magické metody mají tak trochu jiný význam
Tady někdo zavádí kvóty :)

V manuálu PHP ani nikdy a nikde jinde jsem nenarazil na zmínku, že by se magické metody měly používat jen pro nějaký konkrétní politicky korektní účel.
Ugo
Profil
Nox:
ale používal, dělám s ním každý den a každý den nadávám :-P (většinou na věci které pak na oko obhajuji .. globální proměnné hlavně, dopracovat se ke zdroji přes 10 souborů to je vždy muka, ten kdo vymyslel hledání textu v souborech byl génius)
ale je to moje zodpovědnost, přijal sem jí a tak s tím počítám, s těmi mag. metodami jsem měl na mysli v podstatě to co jsi řekl, jen jsem chtě doplnit, že jejich použití z funkce je prostě na to když v každé I/O proměnné potřebuješ nahradit "S" za "Z", ale ne že by ti to mělo bránit napsat si tam if($var == "var") {} elseif() ... , to nikdo neomezuje.

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: