Autor Zpráva
raf.
Profil *
Ahoj. V následujícím příkladě bych chtěl, aby se mi automaticky přepsala reference na objekt z A na B a fungovalo to jak jsem plánoval:
<?php

class A {
        public function f() { return 'a'; }
}

class B {
        public function f() { return 'b'; }
}

class S {
        private static $o;
        static function vratA() {
                $ob = new A;
                self::$o = &$ob;
                return self::$o;
        }
        static function prepisNaB() {
                $ob = new B;
                self::$o = &$ob;
        }
}

$objekt = S::vratA();
var_dump($objekt->f());
S::prepisNaB();
var_dump($objekt->f()); // zde to vrací také a, ale já bych chtěl b
?>

Vypadá to, že php kašle na nějaké reference na objekty a rovnou tam přiděluje reference objektu samotného. Proč teda existují reference na objekty když to nefunguje? Nebo dělám něco špatně?
Jozin
Profil
Zdravím, k tomu nepotřebuješ statickou proměnnou o a v prepisNaB ti chybí return... pokud to chceš s tou proměnnou o, tak oddělej return z vratA a přidej funkci vratO, kde bude jen return self::$o ;)
Jozin
Profil
Mám dost času, tak ti napíšu, jak je to možné udělat. class A a class B zůstává stejný.

<?php

class S
{

  public function getA()
  {
    return new A;
  }

  public function getB()
  {
    return new B;
  }

}

a druhá možnost

<?php

class S
{

  private $o;
  
  public function getA()
  {
    $this->o = new A;
  }

  public function getB()
  {
    $this->o = new B;
  }

  public function getO()
  {
    return $this->o;
  }

}

EDIT: existuje ještě více možností, ale na ukázku stačí toto
TomášK
Profil
raf.:
PHP objektový model neznám, ale pokud to funguje stejně jako jinde, tak je problém v metodě vratA, která vrací objekt a ne referenci na objekt. V okamžiku zavolání return ve vratA se vytvoří kopie objektu, který je uložený ve třídě S a od té doby s ním nemá nic společného, tedy ho ani metoda prepisNaB nemůže změnit.
raf.
Profil *
To si nerozumíme, mě nejde o to, jak vrátit objekty, mě jde o to jak přepsat referenci tak, abych na to nemusel v "hlavním programu" vůbec sahat tzn. nemusel znovu přiřazovat $objekt. U běžných proměnných to jde (např. číslo či řetězec).
raf.
Profil *
TomášK:
No &vratA() na objektech nejde, proto jsem zkoušel takovou obstrukci;
Jozin
Profil
raf.:
Pokud ti jde o to mít super třídu, která obsahuje reference na všechny třídy, které bude aplikace potřebovat, tak se prvně musíš rozhodnout, jestli supertřída bude tyto třídy vytvářet, nebo je bude dostávat z venku. Napíšu tu první možnost:

<?php

class S
{

  private static $_objects = array();

  public static function init()
  {
    //seznam vsech potrebnych trid
    self::$_objects['A'] = new A;
    self::$_objects['B'] = new B;
  }

  public static function getA()
  {
    return self::$_objects['A'];
  }

  public static function getB()
  {
    return self::$_objects['B'];
  }

}

případně se dá použít magická metoda __get atd...

EDIT: udělal jsem tam chybu a musím dodat i zpracování:

<?php

S::init();
$a &= S::getA();
$b &= S::getB();
raf.
Profil *
TomášK:
Ani toto totiž nefunguje:
<?php

class A {
        public function f() { return 'a'; }
}

class B {
        public function f() { return 'b'; }
}

class S {
        private static $o;
        static function &vratA() {
                $ob = new A;
                self::$o = &$ob;
                return self::$o;
        }
        static function prepisNaB() {
                $ob = new B;
                self::$o = &$ob;
        }
}

$objekt = S::vratA();
var_dump($objekt->f());
S::prepisNaB();
var_dump($objekt->f());
?>
raf.
Profil *
Jozin:
Ani ne, jde mi jen o to co jsem psal, změnit referenci uvnitř té třídy. Totiž ta třída vrátí nějaký objekt, se kterým pracuje zbytek aplikace, ovšem kdybych chtěl ten objekt změnit, nejlepší by to bylo udělat změnou reference uvnitř té třídy která ho vrací.
Mastodont
Profil
kdybych chtěl ten objekt změnit, nejlepší by to bylo udělat změnou reference uvnitř té třídy která ho vrací
To ale nejde, protože ty do $objekt přiřadíš odkaz jen jednou a ten pak trvale směřuje na objekt platný v okamžiku přiřazení:
$objekt = S::vratA();
Mastodont
Profil
<?php

class A {
        public function f() { return 'a'; }
}

class B {
        public function f() { return 'b'; }
}

class S {
        public static $o;
        static function init() {
                self::$o = new A;
        }
        static function prepisNaB() {
                self::$o = new B;
        }

}

S::init();
$objekt =& S::$o;
var_dump($objekt->f());
S::prepisNaB();
var_dump($objekt->f()); // zde to vrací b
?>

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0