Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: nullvoid 07. 03. 2018, 08:21:36

Název: PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: 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ěď.
Kód: [Vybrat]
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
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: Kit 07. 03. 2018, 11:11:34
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ší.
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: BoneFlute 07. 03. 2018, 12:14:13
IMHO prostě chybka.
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: dev 07. 03. 2018, 12:38:01
PHP není Java. Je vymakanější.

A VIM je vymakanější než IDEA.
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: jeTuNejakyTopic? 07. 03. 2018, 13:03:50
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:

Kód: [Vybrat]
<?php

class {

    private 
$a "adfs";

    private function 
privateWho() {
        echo 
$a "rwe";
        echo 
__CLASS__.PHP_EOL;
        
    }

    public function 
test() {
        
B::privateWho();           // static::privateWho();
    
}

}

class 
extends {}


$b = new B();

$b->test();     // vytiskne rweA


A to, že tomu nevadí volání přes B:: je fakt humus. :D
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: jeTuNejakyTopic? 07. 03. 2018, 13:05:34
ten příklad beru zpět :D byla to krávovina...
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: nullvoid 07. 03. 2018, 13:50:00
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:

Kód: [Vybrat]
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
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: Kit 07. 03. 2018, 14:23:30
Tohle je také v pořádku, ovšem takové prasárny by se psát neměly.
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: Petr. 07. 03. 2018, 16:01:11
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:

Kód: [Vybrat]
<?php

class {

    private 
$a "adfs";

    private function 
privateWho() {
        echo 
$a "rwe";
        echo 
__CLASS__.PHP_EOL;
        
    }

    public function 
test() {
        
B::privateWho();           // static::privateWho();
    
}

}

class 
extends {}


$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



Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: Havran 07. 03. 2018, 16:23:11
Skusajte tu http://sandbox.onlinephpfunctions.com/ a piste aj verziu PHP :-)
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: jeTuNejakyTopic? 07. 03. 2018, 16:51:58

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

Kód: [Vybrat]
<?php

class {

    

    private function 
privateWho() {
        echo 
$this->a;
        echo 
$this->b;
        
    }

    public function 
test() {
        
B::privateWho();           // static::privateWho();
    
}

}

class 
extends {
    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
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: Kit 07. 03. 2018, 18:01:18
V čem je problém? Takových zbytečných ptákovin se dá vymyslet...
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: . 07. 03. 2018, 18:11:49
A co přesně by na tom nemělo fungovat?!
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: nullvoid 07. 03. 2018, 19:58:55
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.
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: nullvoid 07. 03. 2018, 20:09:00
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í. :)
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: nullvoid 07. 03. 2018, 20:20:37
Na StackOverflow jsem narazil na podobný dotaz (https://stackoverflow.com/questions/11165429/calling-instance-methods-statically-from-within-the-class?answertab=active#tab-top)
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: v 07. 03. 2018, 20:31:07
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í
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: Kit 08. 03. 2018, 10:12:23
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.
Název: Re:PHP: Statické volání soukromé instanční metody rodiče
Přispěvatel: nullvoid 09. 03. 2018, 14:12:43
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.

Kód: [Vybrat]
<?php 
header
("Content-Type: text/plain; charset=utf-8");

class 
{
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 
extends {  
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;
}