Autor Zpráva
sitg
Profil *
Ahoj,

mám problém při vytváření instance singletonu uvnitř jiného singletonu.

Mám následující strukturu kódu:


třída Singleton obsahuje metodu:
	public static function &getInstance() {
		if (($className = \get_called_class()) == __CLASS__)
			throw new \CreateInstanceException('Can not create instance of myself');
		if (! isset(self::$instances[$className]))
			self::$instances[$className] = new $className;
		return self::$instances[$className];
	}


třída Storage rozšiřuje třídu Singleton a obsahuje metodu:
	public function setDriver($driver) {
		self::$driver = $driver;
		return self::getInstance();
	}



třída Security rozšiřuje třidu Singleton a v konstruktoru obsahuje volání:
$storage = Storage::setDriver('TextFile');

Tady ale nastává problém. Protože "Storage::setDriver('TextFile')" nevrátí instanci třídy Storage, ale instanci třídy Security a tak dojde k zacyklení. Řešením je upravit funkci setDriver aby vracela "Storage::getInstance()" namísto "self::getInstance()".

Dokázal by mi prosím někdo vysvětlit proč se to takhle chová?
Majkl578
Profil
Je to tím, že metoda setDriver je volána staticky, ale není tak definována (pomocí static).
To způsobí, že funkce get_called_class vrací název třídy Security místo Storage a vznikne rekurze.
sitg
Profil *
Nějak mi to přijde hodně nelogický. Teď jsem to studoval na php.net a podle toho by nemělo fungovat ani řešení problému se "Storage::getInstance()". Když to vezmu teoreticky: jako první zavolám Storage::setDriver v konstruktoru třídy Security, setDriver provede "self::$driver = $driver", což je funční a už nasvědčuje tomu že self je opravdu chápáno jako jméno Storage. Potom zavolání self::getInstance() volá statickou třídu getInstance(), kde by problém opět vzniknout neměl, protože getInstance() je statická. Problém tudíš musí vyvolávat až nelogické chování funkce get_called_class, která dělá "get_called_class — the "Late Static Binding" class name". Neexistuje nějaký postup jak vyseparovat poslední volanou třídu?
sitg
Profil *
Tak jsem prošel manuály a asi bude nejlogičtější nechat vše jak je (pořebuju aby setDriver nebylo jen static) a budu volat "Storage::getInstance()". Bude tohle vždy funkční nebo mohu čekat v některých případech ještě nějaké překvapení?

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: