Jak funguje @return $this ve vašem IDE?
- petr.pavel
- Člen | 535
Současné anotace v Nette\Forms\Controls\BaseControl způsobují, že po zavolání třeba setRequired() PhpStorm začne považovat RadioList za BaseControl a označí mi následující volání getSeparatorPrototype() jako neplatné. Situací je víc, tohle je jen příklad.
Řešením je anotaci @return self
nahradit anotací
@return $this
nebo @return static
. Je ale potřeba
zjistit, jak jsou na tom ostatní IDE a ApiGen. Prosím vás tedy o pomoc.
Použijte následující kód:
<?php
class A {
/**
* @return self
*/
public function jedna() {}
}
class B extends A {
public function dva() {}
}
$b = new B;
$b->jedna()->dva();
?>
Pokud vaše IDE rovnou neoznačí volání dva()
jako neplatné,
radši vyzkoušejte napovídání, abyste měli jistotu, že opravdu $b
považuje za B.
Napište tedy $b->dv
a CTRL+mezerník (nebo co máte pro
doplňování názvu metody).
Vyzkoušené editory budu doplňovat sem. Pomlčka znamená, že IDE pro
danou anotaci nenapovídá metodu dva()
.
PhpStorm 8.0.1, 8.0.2 | |
---|---|
@return self | – |
@return static | ano |
@return $this | ano |
@return this | – (v anotaci označí this jako neplatnou hodnotu) |
Eclipse 3.7 Indigo +PDT (distribuce od Zend s názvem Eclipse for PHP Developers 3.0.2) | |
@return self | ano (chápe jako static, tj. třídu potomka) |
@return static | – |
@return $this | – |
@return this | – |
Eclipse 4.5 Mars | |
@return self | ano (chápe jako static) |
@return static | – |
@return $this | – |
@return this | – |
NetBeans 8.0.1 | |
@return self | ano |
@return static | ano |
@return $this | – |
@return this | ano |
Nusphere PhpEd 15 | |
@return self | – |
@return static | ano |
@return $this | – |
@return this | – (považuje this za třídu) |
Sublime Text 3 + SublimeCodeIntel 2.0.6 | |
@return self | – |
@return static | – |
@return $this | – |
@return this | – |
ApiGen 4.0.0-RC4 | |
@return self | ano (typ návratové hodnoty A->jedna() uvede jako A, jinak to ani nejde) |
@return static | – (uvede doslovně jako static ) |
@return $this | ? (uvede mixed ; nevím, jak hodnotit) |
@return this | – (uvede doslovně jako this ) |
Zatím to vypadá dost beznadějně, ale Eclipse 3.7 Indigo je
skutečně archaická verze, současná je 4.4 Luna (mezitím jsou dvě jiné
velké verze).
Takže teď je to na vás, předem díky.
Edit po doplnění ApiGenu:
Až teď mi došlo, že ApiGen bude při return $this;
v PHP kódu
volaném potomkem vždycky lhát nebo mlžit – protože nemůže jinak.
Můžeme si jen pomocí anotace vybrat, jestli chceme aby lhal tím, že uvede
svou třídu (přestože se vrací třída potomka) nebo mlžil pomocí
mixed
, které je sice pravda, ale informačně k ničemu.
Editoval petr.pavel (17. 12. 2014 17:44)
- petr.pavel
- Člen | 535
Díky @Xethilos, doplněno. Používáte někdo novější Eclipse? Co takhle Komodo nebo phpDesigner? Něco jiného?
Beru i chytré textové editory s pluginy pro PHP, chci prostě získat přehled. I o tom, co tady kdo v současnosti používá.
- jiri.pudil
- Nette Blogger | 1032
Co jsem narychlo vyzkoušel apigen (4.0.0-RC4), poradí si jenom se
self
(v tom smyslu, že si to přeloží na aktuální třídu),
static
a this
přepíše verbatim a místo
$this
dosadí mixed
.
- Jan Tvrdík
- Nette guru | 2595
Zkusil jsem Eclipse Mars (4.5) a nic jiného, kromě self
nepodporuje, přičemž self
chápe jako static
,
takže následující kód funguje bez problému:
$input = new Nette\Forms\Controls\RadioList();
$input->setRequired(TRUE)->getSeparatorPrototype();
- petr.pavel
- Člen | 535
@jiri.pudil Až teď mi došlo, co vlastně můžeme od ApiGenu čekat. Doplnil jsem nahoru komentář a zajímal by mě tvůj názor (i ostatních).
@JanTvrdík Díky! Zdá se, že od verze 3.7 se tedy nic nezměnilo
:-(
„Funguje bez problémů“ tedy znamená, že metodu
getSeparatorPrototype()
napoví, ano? Verze 3.7 mi nijak
nezvýrazňovala metody, které u třídy nenašla, takže to šlo poznat
jedině přes napovídání/doplňování při psaní.
- Jan Tvrdík
- Nette guru | 2595
ad ApiGen – když tam doplní aktuální třídu, tak rozhodně nelže.
Všechny navrácené hodnoty budou instancí (instanceof
) té dané
třídy. Kdyby PHP byl staticky typovaný jazyk, tak by jako typ návratové
hodnoty byla taky uvedena samotná třída.
- jannek19
- Člen | 47
Přikládám výsledky ze Sublime Text 3 se SublimeCodeIntel pluginem (v2.0.6+st3)
- self – ne
- static – ne
- $this – považuje za neplatnou hodnotu (nenapoví vůbec nic)
- this – ne
- petr.pavel
- Člen | 535
@jannek19: Díky za účast. Výsledek mě dost překvapil, takže
jsem ho pro jistotu ověřil. Fakt že jo, dokud do anotace nenapíšu
@return B
, tak mi ST3 nerozpozná dva
jako funkci. To
je teda materiál…
- David Grudl
- Nette Core | 8228
Pár poznámek:
- jelikož jde o type hinting, tedy napovídání podle
typů, je
@return $this
nesmysl, který by vůbec neměly editory podporovat - protože
this
není klíčové slovo a můžu klidně tak pojmenovat třídu, neměly by editory v žádném případě podporovat@return this
. - nenašel jsem téměř žádnou knihovnu, která by
používala
@return static
@return self
je poměrně běžně používáno ve smyslu fluent interface (ZF2), tady by se mohl „standard“ přizpůsobit
(doplnil jsem do přehledu Nusphere PhpEd 15)
- petr.pavel
- Člen | 535
@pepakriz: Díky za ověření, akorát „self“ má mít „ne“
(tj. „-“), protože se snažíme zjistit, které hodnoty jsou
interpretovány jako static
, nikoliv které hodnoty jsou
podporovány obecně.
- Jan Tvrdík
- Nette guru | 2595
Doplním jak se k tomu staví ostatní frameworky (prošel jsem náhodné kusy kódu):
- Laravel používá zápis
return $this
- Symfony používá zápis
return ClassName
+ výjimečněreturn $this
- Zend používá
return ClassName
- David Grudl
- Nette Core | 8228
V PHP 7 funguje jen „return“ self, static háže parse error. http://3v4l.org/TvJjC
- Jan Tvrdík
- Nette guru | 2595
Btw, interesting thing is that return self works as static and static is parse error http://3v4l.org/TvJjC. This is the end of discussion about @return self vs static.
return self funguje jako return self (tj. stejně jako return X v odkázaném příkladu), ale pochopitelně můžeš vrátit o podtyp.
Kdyby to fungovalo jako return static
, tak by prošlo http://3v4l.org/vpMAS. Je to
z toho důvodu, že PHP nepodporuje „Covariant return types“. V původním RFC
to sice bylo, ale pak kluci z internals zjistili, že vzhledem k architektuře
PHP to nejde naimplementovat.
- petr.pavel
- Člen | 535
Sorry, ztrácím se v tom, co jste chtěli říct, kluci (
@DavidGrudl a @JanTvrdík ). Pochopil jsem, že David upozornil na
novou fíčuru PHP 7, která umožňuje definovat typ návratové hodnoty
metody. Z typů, které tu probíráme zná pouze „self“ a rozumí pod tím
objekt, přes nějž jsme metodu volali. Následující kód
vrátí object(B)#1 (0) { }
<?php
class A { function test() : self { return $this; } }
class B extends A {}
$b = new B;
var_dump($b->test());
?>
Nevím, kde najít definici slova „static“, ale tohle vypadá jako to,
o co mi v tomhle vlákně šlo.
Je mi jedno, co napíšeme do @return
, já jen potřebuju, aby mi
IDE (PhpStorm) napovídal potomky.
Honza pak upozornil, že návratovou hodnotu self nejde použít u přetěžovaných funkcí. Následující kód hodí chybu: `Fatal error: Declaration of B::test() must be compatible with A::test(): A `
<?php
class A { function test(): self { return $this; } }
class B extends A { function test(): self { return $this; } }
?>
Takže to nakonec není ten static, o který mi v tomto vlákně šlo :-) Pochopil jsem to dobře?
Je z toho nějaký závěr? Jedeme dál přes PHPDoc a nadále se
„static“ „self“?
Editoval petr.pavel (15. 8. 2015 14:22)
- petr.pavel
- Člen | 535
Jan Tvrdík napsal(a):
Doplním jak se k tomu staví ostatní frameworky (prošel jsem náhodné kusy kódu):
- Laravel používá zápis
return $this
- Symfony používá zápis
return ClassName
+ výjimečněreturn $this
- Zend používá
return ClassName
Díky! Díval ses na metody, které se běžně volají z potomků?
Když je v PHPDoc rodiče @return TridaRodice
, tak si při
volání $potomek->metoda()
musí IDE myslet, že návratová
hodnota je typu TridaRodice
, ne? To mi nedává moc smysl…
- David Grudl
- Nette Core | 8228
TridaRodice
a self
je z pohledu PHP to samé. To,
co tě zajímá, je static
.
Sám používám @return self
ve smyslu
@return static
(jinak použiju return
ClassName).
Diskuse je vlastně o tom, jestli nahradit @return self
za
@return static
(ostatní varianty $this
a
this
vůbec nepřipadají v úvahu, to první není typ a nelze
použít pro return new static
, to druhé představuje třídu
s názvem this
).
Nahradit by to v podstatě šlo, byť by bylo samozřejmě potřeba opravit ApiGen. (Zkomplikovalo by mi to život s PhpEd 8.1, který typu static nerozumí, což není podstatné, ale je to důvod, proč jsem takovou změnu sám neudělal.)
Nicméně přichází PHP 7, které umožňuje uvádět typy návratových
hodnot, takže spousta anotací @return
bude moci být nahrazena
přímo kódem. A návratový typ může být jen self
, nikoliv
static
.
Což dává smysl. Jenže tím se situace komplikuje ještě víc. Anotace
@return static
nemůže být plně nahrazena typehintem. Buď se na
to rezignuje, nebo se bude kombinovat typehint s anotací, přičemž
absolutně netušíme, jak takovou věc budou chápat editory.
Jinými slovy, situace se v případě PHP7 vrací na začátek.
- Jan Tvrdík
- Nette guru | 2595
@DavidGrudl Pěkně jsi to shrnul.
přičemž absolutně netušíme, jak takovou věc budou chápat editory
Tak jsem zkusil, jak se momentálně chová PhpStorm 9.0.1:
class A
{
public function declaredOnParent()
{
}
public function fluentRealSelf(): self
{
return $this;
}
public function fluentNothing()
{
return $this;
}
/** @return self */
public function fluentPhpDocSelf()
{
return $this;
}
/** @return static */
public function fluentPhpDocStatic()
{
return $this;
}
/** @return $this */
public function fluentPhpDocThis()
{
return $this;
}
/** @return self */
public function fluentPhpDocSelfRealSelf(): self
{
return $this;
}
/** @return static */
public function fluentPhpDocStaticRealSelf(): self
{
return $this;
}
/** @return $this */
public function fluentPhpDocThisRealSelf(): self
{
return $this;
}
}
class B extends A
{
public function declaredOnChild()
{
}
}
$obj = new B();
// resolved as A -> ERROR
$obj->fluentRealSelf()->declaredOnChild();
// resolved as $this
$obj->fluentNothing()->declaredOnChild();
// resolved as A -> ERROR
$obj->fluentPhpDocSelf()->declaredOnChild();
// resolved as static
$obj->fluentPhpDocStatic()->declaredOnChild();
// resolved as $this
$obj->fluentPhpDocThis()->declaredOnChild();
// resolved as A -> ERROR
$obj->fluentPhpDocSelfRealSelf()->declaredOnChild();
// resolved as A|static
$obj->fluentPhpDocStaticRealSelf()->declaredOnChild();
// resolved as A|$this
$obj->fluentPhpDocThisRealSelf()->declaredOnChild();
nothing | self | |
nothing | $this |
self |
self | self |
self |
static | static |
self|static |
$this | $this |
self|$this |
- petr.pavel
- Člen | 535
David Grudl napsal(a):
(ostatní varianty$this
athis
vůbec nepřipadají v úvahu…)
To záleží, jak budeme chápat syntaxi PHPDoc pro @return. Existuje někde oficiální definice PHPDoc? Mám dojem, že ne. Takže je to de facto standard odvozený z jiného jazyka… a proč si ho nepřiohnout. Vnímám to tak, že phpdoc.org je o programu a o tom, co tento program podporuje, ne o standardu.
Ty předpokládáš @return <název střídy|self|static>
.
Pokud bychom byli ze srdce přesvědčení, že ten standard by měl být
rozšířen na
@return <název střídy|self|static|brundibal>
, tak proč
ne? Samozřejmě, je tu otázka, jak tento „rozšířený standard“ budou
podporovat ostatní.
přičemž absolutně netušíme, jak takovou věc budou chápat editory.
Přesně tak. Už teď je v tom roky bordel, těžko říct, jestli PHP 7
self
bude IDE motivovat k nějaké snaze o sjednocení.
Mě z toho vychází, že kromě „počkáme a uvidíme“ můžeme taky
aktivně zaujmout stanovisko :-) a pokusit se ho protlačit. Přeci jen, třeba
právě teď zrovna někdo z PhpEd brouzdá po webu a říká si „Safra, co
s tím @return
self, mrknu se, jak to dělají jinde. Hele Nette,
to je pořádný framework…“
Rád bych ti slíbil, že ti pro to do PhpEd napíšu doplněk, ale to nedám. :-(
- petr.pavel
- Člen | 535
Koukám, tady se už někdo pokoušel dát dohromady vývojáře IDE:
https://groups.google.com/forum/#…
Poslední zpráva z 10.10.13:
Got some positive responses from many projects. Hope it will result in a good discussion and consistent adoption of things such as „@return static“.