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í

Kód: [Vybrat]
class A{
  function __construct(){
    ..
  }
}

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

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

Kód: [Vybrat]
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..

Kód: [Vybrat]
method_exists($a,'__toString');


BoneFlute

  • *****
  • 2 019
    • Zobrazit profil
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 »
Když vytvořím třídu
Kód: [Vybrat]
$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 »
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
Kód: [Vybrat]
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()

Kód: [Vybrat]
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 »
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:
Kód: [Vybrat]
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 019
    • Zobrazit profil
Re:Rozlišení objektu v PHP
« Odpověď #11 kdy: 24. 01. 2018, 21:20:53 »
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 »
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 »
Žá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 019
    • Zobrazit profil
Re:Rozlišení objektu v PHP
« Odpověď #14 kdy: 24. 01. 2018, 21:43:08 »
... 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í:
Kód: [Vybrat]
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ý.