Autor Zpráva
error414-
Profil *
http://cz.php.net/manual/cs/language.oop5.typehinting.php na teto strance je
hinting pro tridy poradne nechapu na co to je a co to je.

jen ze mohu volat

$this->neco(trid $jejiInstance)

ale jak je to pro pole vayne netusim hledal jsem tam priklad ale vubec nenasel.
Muze mi to vzsvetlit?
nightfish
Profil
type hinting je vlastnost, která zaručuje, že metoda převezme jako parametr pouze instanci uvedené třídy (v podstatě typová kontrola na úrovni objektů, nefunguje pro primitivní typy)

v případě, že metoda (např. test(MyClass $obj)) má jako parametr přijímat pouze instanci třídy MyClass, skončí zavolání test($otherObj), kde $otherObj = new OtherClass, chybou...
mila
Profil
Když deklaruješ fci, tak řekneš, co by měla dostat za parametr. Pokud to nedostane, tak skončí s fatal error.
Anonymní
Profil *
Znamená to "typova kontrola".
Ostatní jazyky jako např. Java, C++, apod. Mají typovou kontrolu automaticky zabudovanou a když si vezmete jakým způsobem jsou tyto jazyky koncipovány, tak zjistíte, že bez této kontroly by to ani nešlo.

Type hinting v PHP 5 přišlo s tím, že pro objekty je možné použít typovou kontrolu. Dále tato kotrola je možná použít pro array (viz. manuál)

Při vstupních parametrech do metody či výstupních parametrech občas potřebujete zajistit to, že vrácená data budou ten či onen typ.
Pokud začnete psát OOP kod, tak zjistíte, že bez typové kontroly není možné napsat bezpečnou a dobře fungující aplikaci.

Př.

function a(array $pole)
{
return $pole;
}

$a = "bla";
a($a);
----------------------

Toto vyhodí fatální chybu, parametrem má být pole, nikoli String.
Ono PHPckarovi, který navíc neprogramuje OOP, těžko vysvětluje, k čemu je toto dobré. Ale při psaní OOP Vám to dojde automaticky :)

Existuje další věc, která bez typove kontroly není možná "polymorfismus". Znamená to, že podle počtu a typu parametrů v metodě se může pokaždé volat jiná metoda. Toto v PHP nefunguje a důvodem je to, že primitivní datové typy jako int, string, float, boolean není možné typovou kontrolou kontrolovat.
Zkuste se podívat např. na Javu, k čemu je toto dobré.

P.S. Díky bohu alespon za to málo, co v PHP5 pro type hinting je: array a objects.
error414-
Profil *
Anonymní


JJ dik yas tak blbej na oo nejsem chapu na co to pouzit
je to misto kontroly ve funkci kdyz kontroluju jestli prichozi instance je instanci objektu blabla
takhle to osetrim rovnou.

"Když deklaruješ fci, tak řekneš, co by měla dostat za parametr. Pokud to nedostane, tak skončí s fatal error." tphle me uplne stacilo

moc diky
error414-
Profil *
jeste dodatek tohle je jedine forum ktere me dokazalo poradi

moc diky
mila
Profil
Ostatní jazyky jako např. Java, C++, apod. Mají typovou kontrolu automaticky zabudovanou a když si vezmete jakým způsobem jsou tyto jazyky koncipovány, tak zjistíte, že bez této kontroly by to ani nešlo.
Naopak když se podíváme, jak je koncipována typová kontrola v php, tak zjistíme že je vlastně na nic. Příklad:
function foo (myClass $in) {..}

if (false) {
foo (5);
}

Protože podmínka neprojde, není fce nikdy zavolána, typová kontrola provedena, nic se nestane. Řekněme, že místo false je tam podmínka, která může být splněna, jen během testování se to nestalo. Web přijde do ostrého provozu, podmínka něco se změní, a konec... (tohle je jednoduchý příklad, ale všichni víme, kolika neočekávanými cestami může vlastní program jít:))

Protože php je slabě typovaný jazyk, lze kontrolu provádět až za běhu. Naopak v silně typovaném jazyce vyhodí chybu už překladač. Tzn. i když na volání nedojde, víš, že je tam chyba.
Když si dáš na začátek fce
if (!is_a ($in, 'myClass')) trigger_error ("Bad param.", E_USER_ERROR)

tak výsledek bude úplně totožný. Vlastně o malinko lepší, protože chybu, kterou si takto vyhodíš, můžeš pomocí set_error_handler ošetřit (napsat uživateli sorry).

Dále tato kotrola je možná použít pro array (viz. manuál)
Od php 5.1

Existuje další věc, která bez typove kontroly není možná "polymorfismus". Znamená to, že podle počtu a typu parametrů v metodě se může pokaždé volat jiná metoda. Toto v PHP nefunguje a důvodem je to, že primitivní datové typy jako int, string, float, boolean není možné typovou kontrolou kontrolovat.
V php to funguje, jen malinko jinak. Viz fce func_get_args(), func_num_args() a defaultní hodnoty parametrů fce, gettype(), is_*...
Nedefinuješ jednu funkce několikrát pro různé parametry, ale jen jednou, a na začátku si parametry zjistíš.

P.S. Díky bohu alespon za to málo, co v PHP5 pro type hinting je: array a objects.
Dle mého názoru je to prakticky k ničemu, důvod jsem vysvětloval nahoře.
Oswald
Profil
Jenom poznámka - v pětce už existuje operátor "instanceof" a funkce "is_a" je proto deprecated.
anode
Profil
P.S. Díky bohu alespon za to málo, co v PHP5 pro type hinting je: array a objects.
To by se už nejednalo o PHP. Současné rozlišení skalárních typů, pole a objektů je ale podle mě užitečné. Proč bych měl na začátek každé funkce, kde chci kontrolovat správný typ objektu, vkládat jakýsi kód, který dělá totéž, co jeden type-hint? Navíc takhle, když aplikaci píšu, vidím rovnou, co funkce chce. Nemusím se dívat do jejího těla, stačí hlavička. O možnosti automatické dokumentace nebo potenciální kontrole přímo editorem nemluvě... Prostě když vím, že tahle funkce bude brát pouze jednu třídu, protože s ní nějak pracuje, tak to tak zkrátka bude. Když po ní budu chtít, aby zpracovávala i jiné třídy, stejně ji musím přepsat/upravit.
mila
Profil
Proč nepoužívám kontrolu tipů v php?
- Končí fatal error. Jak jsem psal, nejde ošetřit pomocí set_error_handler. Myslím, že pokud dojde ke kritické chybě, měli bychom se uživateli omluvit (a poslat příslušnou hlavičku). Takto jen skript někde v půlce chcípne.
- Připravuje mě o polymorfismus a defaultní hodnoty parametrů.
- Fce volám se správnými parametry. Pokud náhodou dostane špatný, tak je to nějaké nečekané chování skriptu. Při vývoji to zjistím z chybové hlášky a dva řádky dál, při běhu je už stejně pozdě.
- Když už kontroluji paramtry, tak mi přijde lepší, když je to u všech stejně. Ne objety v definici, ostatní v těle.
- Nefunguje v php4
Oswald
Profil
- Končí fatal error. Jak jsem psal, nejde ošetřit pomocí set_error_handler. Myslím, že pokud dojde ke kritické chybě, měli bychom se uživateli omluvit (a poslat příslušnou hlavičku). Takto jen skript někde v půlce chcípne.

set_exception_handler

Update: to s tím vlastně nesouvisí, příště už opravdu budu lépe číst :)

- Připravuje mě o polymorfismus a defaultní hodnoty parametrů.

Ne tak docela, např.:


class C {

function f(array $a = null) {
var_dump($a);
}
function ff(array $a = array('default')) {
var_dump($a);
}

}

$c = new C;

$c->f();
$c->f(array('foo'));
$c->ff();
$c->ff(array('specific'));
anode
Profil
Mila:
- když nasazuji systém do provozu, asi ho napřed důkladně otestuji (což jsem ale dělal již v průběhu jeho tvorby, ať žije Test Driven Development :)
- když už používám polymorfismus, mají vždy všechny třídy, které chci použít, společného předka (ať už jde o rozhraní nebo abstraktní třídu). Potom do type-hintu uvedu tohoto předka; defaultní hodnoty u objektů? a jak je používáte bez typu-hintů? nic jako function foo($bar=new Bar()) {} samozřejmě nefunguje. a pokud chcete, aby byl parametr nepovinný, function foo(Bar $bar = null) { } naopak funguje dobře. defaultní hodnoty parametrů zkrátka s type-hintingem nesouvisejí.
- ad kontrola parametrů: já skalární typy nekontroluji. Proč bych se měl zajímat, jestli jsem dostal int nebo string? Volající funkce asi ví nejlíp, co mi vrazit, abych to ještě přežvýkal. Kontroluji pouze vstup od uživatele. Ano, ve velice specifických případech kontroluji ve funkcích i předaný typ, ale je to opravdu výjimka.
- nevím jak Vy, já už jsem se na PHP4 vykašlal. Když chci používat pokročilejší práci s objekty, proč bych se měl se 4kou otravovat? PHP5 je dnes zcela běžně k dispozici na všech slušných hostingových službách.
mila
Profil
když nasazuji systém do provozu, asi ho napřed důkladně otestuji (což jsem ale dělal již v průběhu jeho tvorby, ať žije Test Driven Development :)
Chyba se může vždycky objevit. Ono stačí třeba ta chvilka, kdy přes ftp nahrávám na web novou verzi. V php je také spousta fcí, které vrací objekt, ale při neúspěchu false. A dokud vše funguje jak má, tak mě často ani nenapadne, že vrací něco jiného než ten objekt.
Argument, že chyby nepotřebuji ošetřit, protože tam nejsou, neberu.

Ono je to hlavně velmi elegantní. Napíšu si funkci, která napíše "Sorry.." a pošle hlavičku 505. Když vím, že jsem v koncích, tak jen zavolám triger_error.
Nepodařilo se připojit k databázi? Chybí důležitá knihovna? Dostal jsem nějaký úplně nečekaný argument. Nic lepšího než omluvu uživateli nevymyslím... Je to lepší, než bez vysvětlení skončit.

- když už používám polymorfismus, mají vždy všechny třídy, které chci použít, společného předka (ať už jde o rozhraní nebo abstraktní třídu). Potom do type-hintu uvedu tohoto předka; defaultní hodnoty u objektů? a jak je používáte bez typu-hintů? nic jako function foo($bar=new Bar()) {} samozřejmě nefunguje. a pokud chcete, aby byl parametr nepovinný, function foo(Bar $bar = null) { } naopak funguje dobře. defaultní hodnoty parametrů zkrátka s type-hintingem nesouvisejí.
Asi jsem použil špatné slovo (polymorfismus), myslel jsem různé chování fce, podle typu (množství) parametrů, které dostane.
function foo(Bar $bar = null) { }
jsem měl pocit, že nefunguje, a ono ano! Mám pocit (co jsem rychle vygoogloval), že to jde až do PHP 5.1, já to původně zkoušel s PHP 5.0.
To je příjemná věc, ale programovat jen pro PHP5.1 je už docela ostré. Stále ale nejde udělat věci typu - dostane buď object nebo string.

- ad kontrola parametrů: já skalární typy nekontroluji. Proč bych se měl zajímat, jestli jsem dostal int nebo string? Volající funkce asi ví nejlíp, co mi vrazit, abych to ještě přežvýkal. Kontroluji pouze vstup od uživatele. Ano, ve velice specifických případech kontroluji ve funkcích i předaný typ, ale je to opravdu výjimka.
Souhlasím, také většinou nekontroluji. Ale když "Volající funkce asi ví nejlíp, co mi vrazit,..", tak to platí i pro objekty.
btw často místo kontroly používám konstrukce typu "(array) $param"

- nevím jak Vy, já už jsem se na PHP4 vykašlal. Když chci používat pokročilejší práci s objekty, proč bych se měl se 4kou otravovat? PHP5 je dnes zcela běžně k dispozici na všech slušných hostingových službách.
V tomhle nemám ještě moc jasno.
Rád bych to udělal, ale ono pokud si někdo nechá u mě udělat nové stránky, tak je těžké mu vysvětlit, že má změnit hosting, se kterým je spokojen.
anode
Profil
Právěže mně moc elegantní nepřipadá vždycky na začátku funkce ověřovat, jestli je daný argument (a může jich být i více) správného typu. Máte pravdu, že je vhodné uživateli při chybě něco sdělit. Co takhle:
<?php
class Foo {}
function bar(Foo $a) { echo 'wheee'; }
function sorry() { if (!defined('OK')) echo 'Prominte'; }
register_shutdown_function('sorry');
@bar(5);
define('OK',1);
?>
Když se volá bar(new Foo()); , proběhne vše v pořádku a vypíše se 'wheee', naopak v uvedeném případě se vypíše 'Prominte'. Stačí na konci běhu skriptu říct, že doběhl v pořádku. A vychytá to i všechny další fatální chyby (parse errory v includovaných skriptech například). Je to jen nahození, vytvořil jsem to teď, ale připadá mi to příjemnější, než pořád něco testovat, když to engine může udělat za mě.

Pravda, zmiňované je skutečně až od PHP 5.1 :(
Stále ale nejde udělat věci typu - dostane buď object nebo string.
Type-hinting v PHP je navržený jako jednoduchá kontrola. A alespoň já jsem zatím nikdy nepoužil funkci, která by zpracovala objekt i řetězec. Pokud Vy ano (opět předpokládám v nějakém výjimečném případě), type-hinting nepoužijete a zkontrolujete vstup ručně, což stejně musíte udělat, pokud chcete umět zpracovat objekt i řetězec.

btw často místo kontroly používám konstrukce typu "(array) $param"
Na tohle šikovné řešení jsem už zase zapomněl :) Zrovna jsem dělal funkci, co umí zpracovat pole i skalár. Ale přetypovat skalár na pole, abych ho zase převedl na skalár... Ale jo, dobrá :)
mila
Profil
Co takhle: ...
Tohle funguje, nšdávno jsem to řešil. Jediná chybička kterou jsem našel je, že nejdou v shutdown_function poslat hlavičky. Ta mi přijde dost důležitá, aby vyhledávač neindexoval chybovou stránku. Nebo přesněji to jde od php 5.1

Vymyslel jsem na to takový trik - místo
register_shutdown_function('sorry'); 

toto:
ob_start ('sorry');

Fce sorry pak dle nějakého nastavení (v příkladu konstanta OK), buď vrátí co dostala, nebo pošle hlavičku a vrátí chybovou hlášku. Ten buffering je stejně třeba, protože pokud chci posílat hlavičky, tak nesmím nic vypsat.

Čekal jsem, jestli mě někdo dostane, když jsem psal, že chyba nejde ošetřit:)

dostane buď object nebo string
Tady mě napadá spousta příkladů, ale je to asi o stylu. Někdo si napíše dvě fce, já to radši nacpu do jedné. Třeba teď něco dělám s xml dom, a mám fci addNode. Ta bere objekt node, nebo string id (zjednodušeně). Nebo mám šablonu, do které cpu fcí set data. Ta mohou být skalár, nebo další šablona.

Ještě mě napadlo: nebylo by lepší, při chybném argumentu, místo fatal error vyhodit exception?

Mě přijde, že typová kontrola v php mi nic nepřináší (narozdíl od silně typovaných jazyků). Jediné co dovede je zabít skript, když jsem jako programátor udělal chybu - což by se stalo stejně, protože bude zavolána neexistující fce.
Asi si to většina lidí nemyslí, jinak by ji tam nepřidali.
anode
Profil
Čekal jsem, jestli mě někdo dostane, když jsem psal, že chyba nejde ošetřit:)
Beru to jako pochvalu :) S tím output bufferem je to skutečně dobrý nápad, na to jsem si nevzpomněl.
Osobně si myslím, že fatal error je zbytečně silný, ale lepší řešení není (ve smyslu vyhození chyby jiné úrovně), protože jakmile se s objektem pracuje a volá se jeho neexistující metoda, stejně skončíme fatální chybou. Vyhození výjimky by proto bylo řešením více než vhodným.
Typová kontrola není k ničemu. Umožňuje elegantně ověřit, zda dostáváme to, co očekáváme. Nemusí být zavolána neexistující funkce (metoda) - když např. jen objektu nastavíme nějakou vlastnost, bez reptání ji přece PHP nastaví. Skript ale probíhá nečekaným způsobem.
Mimochodem, v PHP6 bude přidán i type-hinting na návratové hodnoty funkcí/metod. To mi teprv připadá zbytečné...
Toto téma je uzamčeno. Odpověď nelze zaslat.