Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: nullvoid 07. 03. 2018, 08:21:36
-
Zdravím, trochu jsem experimentoval s Late Static Bindings a zkoušel různé kombinace použití parent::, self:: a static::, až jsem se dostal k následující podivnosti, která mi neleze do hlavy. Jak je vůbec možné, že script neohlásí žádný warning a ani deprecated hlášku o statickém volání nestatické metody?
V konfiguraci PHP mám error_reporting nastaven na E_ALL. Díky za odpověď.
class A {
private function privateWho() {
echo __CLASS__.PHP_EOL;
}
public function test() {
B::privateWho(); // static::privateWho();
}
}
class B extends A {}
$b = new B();
$b->test(); // vytiskne A
-
Ta metoda se jednoduše zavolá staticky, ničemu to nevadí. Problém by nastal teprve pokud by se snažila použít nějakou instanční proměnnou.
PHP není Java. Je vymakanější.
-
IMHO prostě chybka.
-
PHP není Java. Je vymakanější.
A VIM je vymakanější než IDEA.
-
Zdravím, trochu jsem experimentoval s Late Static Bindings...
Troufám si říct, že jste objevil bug v PHP. Minimálně v tom, že ani mírně rozšířený příklad nehodí error/warning:
<?php
class A {
private $a = "adfs";
private function privateWho() {
echo $a . "rwe";
echo __CLASS__.PHP_EOL;
}
public function test() {
B::privateWho(); // static::privateWho();
}
}
class B extends A {}
$b = new B();
$b->test(); // vytiskne rweA
A to, že tomu nevadí volání přes B:: je fakt humus. :D
-
ten příklad beru zpět :D byla to krávovina...
-
Zdravím, trochu jsem experimentoval s Late Static Bindings...
Troufám si říct, že jste objevil bug v PHP. Minimálně v tom, že ani mírně rozšířený příklad nehodí error/warning:
Nevím, jestli je to bug, pochybuju o tom, nicméně vaše rozšíření příkladu mě přivedlo k:
class A {
private $a = "private ";
private function privateWho() {
echo $this->a.__CLASS__.PHP_EOL;
}
public function test() {
B::privateWho();
}
}
class B extends A {}
$b = new B();
$b->test(); // private A
-
Tohle je také v pořádku, ovšem takové prasárny by se psát neměly.
-
Zdravím, trochu jsem experimentoval s Late Static Bindings...
Troufám si říct, že jste objevil bug v PHP. Minimálně v tom, že ani mírně rozšířený příklad nehodí error/warning:
<?php
class A {
private $a = "adfs";
private function privateWho() {
echo $a . "rwe";
echo __CLASS__.PHP_EOL;
}
public function test() {
B::privateWho(); // static::privateWho();
}
}
class B extends A {}
$b = new B();
$b->test(); // vytiskne rweA
A to, že tomu nevadí volání přes B:: je fakt humus. :D
Mě to teda hodí chybu
Notice: Undefined variable: a in /tmp/test.php on line 8
rweA
-
Skusajte tu http://sandbox.onlinephpfunctions.com/ a piste aj verziu PHP :-)
-
Mě to teda hodí chybu ...
Hned po odeslání jsem si uvědomil, že mi tam chybí $this-> (nějakou dobu jsem nepsal v PHP). Pokud by tam bylo, tak to nomrálně tu privátní proměnnou vypíše.
Ovšem další (alespoň pro mě) zajímavý příklad: :D
<?php
class A {
private function privateWho() {
echo $this->a;
echo $this->b;
}
public function test() {
B::privateWho(); // static::privateWho();
}
}
class B extends A {
protected $a = "aaaaaa";
private $b = "bbbbbb";
}
$b = new B();
$b->test(); // vytiskne aaaaaa a pak hodí Uncaught Error
tzn. nemá problém vypsat protected property třídy B :D
-
V čem je problém? Takových zbytečných ptákovin se dá vymyslet...
-
A co přesně by na tom nemělo fungovat?!
-
A co přesně by na tom nemělo fungovat?!
Minimálně bych očekával, že se interpretru jazyka nebudou podobné konstrukce zamlouvat a bude o jejich nevhodnosti autora informovat vhodnou hláškou.
Jde mi prostě o to, že použiju-li Potomek::soukromaMetodaRodice() byť v těle veřejné metody rodiče, snažím se o volání metody v kontextu třídy potomka, tedy se snažím volat překrývající implementaci metody v potomkovi, a není-li tam nalezena, použije se metoda rodiče, nebo je-li soukromá, jako v tomto případě, obdržím chybovou hlášku. Možná ale jen dědičnost a modifikátory přístupu špatně chápu.
-
V čem je problém? Takových zbytečných ptákovin se dá vymyslet...
Já chápu, že je to nesmyslná konstrukce a blbost, která nemá se skutečným programováním mnoho společného, ale já se jednoduše snažím i v blbostech hledat logiku, což je asi mým prokletím. :(
Omlouvám se tedy za "znečišťování" fóra podobnými nonsensy. Příště se tomu pokusím vyhnout. Díky za pochopení. :)
-
Na StackOverflow jsem narazil na podobný dotaz (https://stackoverflow.com/questions/11165429/calling-instance-methods-statically-from-within-the-class?answertab=active#tab-top)
-
V čem je problém? Takových zbytečných ptákovin se dá vymyslet...
Já chápu, že je to nesmyslná konstrukce a blbost, která nemá se skutečným programováním mnoho společného, ale já se jednoduše snažím i v blbostech hledat logiku, což je asi mým prokletím. :(
Omlouvám se tedy za "znečišťování" fóra podobnými nonsensy. Příště se tomu pokusím vyhnout. Díky za pochopení. :)
osobně považuju váš dotaz za zcela legitimní
-
V čem je problém? Takových zbytečných ptákovin se dá vymyslet...
Já chápu, že je to nesmyslná konstrukce a blbost, která nemá se skutečným programováním mnoho společného, ale já se jednoduše snažím i v blbostech hledat logiku, což je asi mým prokletím. :(
Omlouvám se tedy za "znečišťování" fóra podobnými nonsensy. Příště se tomu pokusím vyhnout. Díky za pochopení. :)
Doporučuji při takových pokusech zapnout všechna chybová hlášení, včetně noticek. Odpoví na mnoho otázek.
Nebýt takových šťouralů, svět by byl dokonalý ... a strašně nudný. Díky za takové dotazy.
-
Tak jsem příklad ještě trochu upravil a přidal výpisy debug_backtrace(), což činí věci o něco jasnějšími. Vypadá to jednoduše tak, že volání instanční metody statickým způsobem, tj. B::privateWho() je naprosto totožné, jako volání $this->privateWho().
Vkládám zdrojový kód s komentáři, protože sandbox.onlinephpfunctions.com má debug_backtrace() z bezpečnostních důvodů zakázánu.
<?php
header("Content-Type: text/plain; charset=utf-8");
class A {
private function privateWho() {
debug_print_backtrace();
}
public function runFn($fn) {
debug_print_backtrace();
$fn();
}
public function testA() {
debug_print_backtrace();
$this->privateWho();
}
public function testB() {
debug_print_backtrace();
B::privateWho();
}
}
class B extends A {
public function testC() {
debug_print_backtrace();
B::privateWho();
}
}
$b = new B();
try {
#0 A->privateWho() called at [index.php:16]
#1 A->testA() called at [index.php:36]
$b->testA();
} catch (Error $e) {
echo $e->getMessage().PHP_EOL;
}
try {
#0 A->privateWho() called at [index.php:21]
#1 A->testA() called at [index.php:42]
$b->testB();
} catch (Error $e) {
echo $e->getMessage().PHP_EOL;
}
try {
#1 B->testC() called at [index.php:48]
$b->testC();
} catch (Error $e) {
# Call to private method A::privateWho() from context 'B'
echo $e->getMessage().PHP_EOL;
}
try {
#0 A->runFn(Closure Object ()) called at [index.php:56]
$b->runFn(function() {
B::privateWho();
});
} catch (Error $e) {
# Call to private method A::privateWho() from context ' '
echo $e->getMessage().PHP_EOL;
}