Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Matěj 24. 01. 2018, 16:12:21

Název: Rozlišení objektu v PHP
Přispěvatel: Matěj 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');
Název: Re:Rozlišení objektu v PHP
Přispěvatel: BoneFlute 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?
Název: Re:Rozlišení objektu v PHP
Přispěvatel: to_je_jedno 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()
Název: Re:Rozlišení objektu v PHP
Přispěvatel: Kit 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í.
Název: Re:Rozlišení objektu v PHP
Přispěvatel: Matěj 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;
Název: Re:Rozlišení objektu v PHP
Přispěvatel: Kit 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í.
Název: Re:Rozlišení objektu v PHP
Přispěvatel: Matěj 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. ;)
Název: Re:Rozlišení objektu v PHP
Přispěvatel: to_je_jedno 24. 01. 2018, 20:33:07
mam pocit, ze vymyslis neco spatneho
Název: Re:Rozlišení objektu v PHP
Přispěvatel: Kit 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;
    }
}
Název: Re:Rozlišení objektu v PHP
Přispěvatel: Matěj 24. 01. 2018, 21:09:53
Žádnou chybu nevidím..
Název: Re:Rozlišení objektu v PHP
Přispěvatel: jiřin 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
Název: Re:Rozlišení objektu v PHP
Přispěvatel: BoneFlute 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číš?!
Název: Re:Rozlišení objektu v PHP
Přispěvatel: Kit 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é.
Název: Re:Rozlišení objektu v PHP
Přispěvatel: Kit 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 ''.
Název: Re:Rozlišení objektu v PHP
Přispěvatel: BoneFlute 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ý.
Název: Re:Rozlišení objektu v PHP
Přispěvatel: Matěj 24. 01. 2018, 21:56:46
Já pořád nechápu, proč tedy řešíte (string)? Není problém v tom, že by to nevracelo string, je problem v tom výsledku, stejná konstrukce a výsledek je 1 ale očekávaný výsledek je 2.
Název: Re:Rozlišení objektu v PHP
Přispěvatel: BoneFlute 24. 01. 2018, 22:01:02
Já pořád nechápu, proč tedy řešíte (string)? Není problém v tom, že by to nevracelo string, je problem v tom výsledku, stejná konstrukce a výsledek je 1 ale očekávaný výsledek je 2.

No tak evidentně to tak úplně stejná konstrukce není, když se to chová jinak, že jo.
Název: Re:Rozlišení objektu v PHP
Přispěvatel: Kit 25. 01. 2018, 02:36:06
Já pořád nechápu, proč tedy řešíte (string)? Není problém v tom, že by to nevracelo string, je problem v tom výsledku, stejná konstrukce a výsledek je 1 ale očekávaný výsledek je 2.

Místo výpočtu a převodu na string je předán přímo ten objekt. Operace se tedy neprovede, protože to jsi po tom objektu nechtěl.

Porušuješ základní pravidlo: Metoda má něco dělat (procedura) nebo vracet stav (funkce). Nikdy obojí současně.