Rozlišení objektu v PHP

Matěj

Rozlišení objektu v PHP
« kdy: 24. 01. 2018, 16:12:21 »
Ahoj, jak rozpoznat co objekt vrací

class A{
  function __construct(){
    ..
  }
}

class A{
  function __toString(){
    return ..
  }
}


Když vytvořím třídu
$a = new A();
a dám testovat na objekt, tak je to pořád objekt

if ( is_object($a)){
  //je to objekt
}


myslel jsem, že díky magické metodě __toString() se stane z objektu string. Ne, že se nestane z objektu string, ale dokonce stále můžu volat třeba jiné metody.
Tak že otázka, může to kód nějak zjistit/rozlišit? Napadlo mě pouze tohle, ale nevím no..

method_exists($a,'__toString');


BoneFlute

  • *****
  • 2 155
Re:Rozlišení objektu v PHP
« Odpověď #1 kdy: 24. 01. 2018, 16:29:05 »
Nevytvoříš dvě třídy se stejným jménem.

Objekty rozlišíš podle toho, jaký mají typ. Funkce get_class.

Metoda __toString() nijak neuprávuje svůj objekt. Tato metoda vrací textovou reprezentaci objektu. Slouží to k tomu, aby se dalo zapsat echo "Obsah objektu {$a}.". Nevrací jméno třídy, ale textovou reprezentaci instance, obsahu.

Můžeš lépe popsat, o co ti jde?

Re:Rozlišení objektu v PHP
« Odpověď #2 kdy: 24. 01. 2018, 16:43:01 »
Citace od: Matěj kdy 24. 01. 2018, 16:12:21
Když vytvořím třídu
$a = new A();
Takhle vytvaris objekt(instanci tridy) a nikoliv tridu.
Jak funguje metoda __toString() uz kolega popsal. Objekt bude vzdy objektem - neexistuje duvod, aby byl stringem. Avsak existuji obcas dobre duvody proc mit implementovanou metodu toString()
Děkuji za možnost editace příspěvku.

Kit

Re:Rozlišení objektu v PHP
« Odpověď #3 kdy: 24. 01. 2018, 16:54:08 »
K rozlišení objektů slouží operátor instanceof, ovšem v dobrých skriptech se to nepoužívá. K čemu vlastně potřebuješ rozpoznávat, co obekt vrací? Prostě tu metodu implementuj v každém objektu, který může být tímto způsobem volán a tu metodu volej bez ptaní.

Matěj

Re:Rozlišení objektu v PHP
« Odpověď #4 kdy: 24. 01. 2018, 19:14:14 »
Citace od: BoneFlute kdy 24. 01. 2018, 16:29:05
Můžeš lépe popsat, o co ti jde?

Když pominu můj původní dotaz, který stejně směřoval k tomuto problému, tak jde o to, že kámen úrazu je to, že
se nedají volat z metody __toString() jiné metody, teda dají ale změny se neprojeví v objektu..
Třeba tohle vrátí výsledek správně - nastaveno : 2

class A{
        public $v=1;

        public function nastav(){
                $this->v=2;
                return 'nastaveno : ';
        }
}

class B{
        public function __construct($a){
                $this->a=$a;
                $this->r=$this->a->nastav();
        }

        public function __toString(){
                return $this->r;
        }
}

class C{
        public function __construct (){
                $this->a=new A();
                $this->b=new B($this->a);
        }

        public function __toString(){
                return $this->b.$this->a->v;
        }
}

$c=new C();

echo $c;


no a tohle vrátí výsledek špatně - nastaveno : 1, a to jenom proto, že jsem to volal z metody __toString()


class A{
        public $v=1;

        public function nastav(){
                $this->v=2;
                return 'nastaveno : ';
        }
}

class B{
        public function __construct($a){
                $this->a=$a;
        }

        public function __toString(){
                return $this->r=$this->a->nastav();
        }
}

class C{
        public function __construct (){
                $this->a=new A();
                $this->b=new B($this->a);
        }

        public function __toString(){
                return $this->b.$this->a->v;
        }
}

$c=new C();

echo $c;


Kit

Re:Rozlišení objektu v PHP
« Odpověď #5 kdy: 24. 01. 2018, 19:34:29 »
Možná je to tak správně, neboť metoda __toString() by v žádném případě neměla nic nastavovat.

Přiznám se, že se i v tak krátkém kódu docela ztrácím. Možná proto, že mezi těmi třídami je příliš mnoho zbytečných vnitřních závislostí.

Matěj

Re:Rozlišení objektu v PHP
« Odpověď #6 kdy: 24. 01. 2018, 20:14:17 »
Citace od: Kit kdy 24. 01. 2018, 19:34:29
Možná je to tak správně, neboť metoda __toString() by v žádném případě neměla nic nastavovat.

Přiznám se, že se i v tak krátkém kódu docela ztrácím. Možná proto, že mezi těmi třídami je příliš mnoho zbytečných vnitřních závislostí.

Ano, je možný, že to není chyba ale vlastnost.
Taky to napsat bylo docela složitý, abych nasimuloval ten jev. ;)

Re:Rozlišení objektu v PHP
« Odpověď #7 kdy: 24. 01. 2018, 20:33:07 »
mam pocit, ze vymyslis neco spatneho
Děkuji za možnost editace příspěvku.

Kit

Re:Rozlišení objektu v PHP
« Odpověď #8 kdy: 24. 01. 2018, 20:37:40 »
Tak jsem si to zkopíroval a vyzkoušel. Ve třídě C máš chybu ve funkci __toString(). Vyzkoušej tohle:
class C {
    public function __construct () {
        $this->a = new A();
        $this->b = new B($this->a);
    }

    public function __toString() {
        return '' . $this->b . $this->a->v;
    }
}

Matěj

Re:Rozlišení objektu v PHP
« Odpověď #9 kdy: 24. 01. 2018, 21:09:53 »
Žádnou chybu nevidím..

jiřin

Re:Rozlišení objektu v PHP
« Odpověď #10 kdy: 24. 01. 2018, 21:12:15 »
Takže vytvoříš objekt C, který vytvoří objekt A a tento předá do konstruktoru objektu B kvůli vypsání vlastnosti v objektu A. A jinak doma všichni zdrávi? Já myslím, že svět je jednoduchý a měli bychom ho tak udržovat. Nepředávej objekty do konstruktorů, vytvoř jim privátní a veřejné vlastnosti a předávej tyto. Používej dědičnost. Vytvoř si objekty, které něco řeší a mezi nimi předávej zprávy. Určitě to není předávání objektu do konstruktoru. Přečti si manuál - http://php.net/manual/en/language.oop5.magic.php#object.tostring . Metoda __toString řeší něco jiného než předání tvého vlastního stringu

BoneFlute

  • *****
  • 2 155
Re:Rozlišení objektu v PHP
« Odpověď #11 kdy: 24. 01. 2018, 21:20:53 »
Citace od: jiřin kdy 24. 01. 2018, 21:12:15
Nepředávej objekty do konstruktorů, vytvoř jim privátní a veřejné vlastnosti a předávej tyto. Používej dědičnost.

Co ho to učíš?!

Kit

Re:Rozlišení objektu v PHP
« Odpověď #12 kdy: 24. 01. 2018, 21:21:12 »
Citace od: jiřin kdy 24. 01. 2018, 21:12:15
Takže vytvoříš objekt C, který vytvoří objekt A a tento předá do konstruktoru objektu B kvůli vypsání vlastnosti v objektu A. A jinak doma všichni zdrávi? Já myslím, že svět je jednoduchý a měli bychom ho tak udržovat. Nepředávej objekty do konstruktorů, vytvoř jim privátní a veřejné vlastnosti a předávej tyto. Používej dědičnost. Vytvoř si objekty, které něco řeší a mezi nimi předávej zprávy. Určitě to není předávání objektu do konstruktoru. Přečti si manuál - http://php.net/manual/en/language.oop5.magic.php#object.tostring . Metoda __toString řeší něco jiného než předání tvého vlastního stringu

Brzdi. Objekty se do konstruktorů běžně předávají - bez toho bys neudělal DI. Nadužívání dědičnosti tady řešíme stále, konkrétně v uvedeném případě dědičnost své místo nemá. Metoda __toString() může poskytovat jakýkoli řetězec, který uzná za vhodné.

Kit

Re:Rozlišení objektu v PHP
« Odpověď #13 kdy: 24. 01. 2018, 21:25:31 »
Citace od: Matěj kdy 24. 01. 2018, 21:09:53
Žádnou chybu nevidím..

Metoda _toString() má vracet řetězec. Místo toho jí dáváš objekt $this->b, což řetězec rozhodně není. Musíš ho přetypovat na string nebo zřetězit za ''.

BoneFlute

  • *****
  • 2 155
Re:Rozlišení objektu v PHP
« Odpověď #14 kdy: 24. 01. 2018, 21:43:08 »
Citace od: Matěj kdy 24. 01. 2018, 19:14:14
... tak jde o to, že kámen úrazu je to, že
se nedají volat z metody __toString() jiné metody, teda dají ale změny se neprojeví v objektu.
Hehe, to je docela zajímavé gotchas, tuhle ještě neznám.

Podle všeho to vypadá, že se prostě jenom vyhodnocují volání těch dvou argumentů v opačném pořadí (tedy odzadu), než jak by si čekal. Stačí přidat přetypování:

class C{
        public function __toString(){
                return ((string)$this->b) . $this->a->v;
        }
}


Každopádně taky mi to přijde na můj vkus dost překombinovaný.