Передача данных в уже созданый объект?

O
На сайте с 23.09.2014
Offline
76
654

Иллюстрирую такой код для примера, который состоит из 5 классов.

- Класс Chief создает и возвращает объекты и имеет четыре наследника.

- Класс библиотеки Library с различными методами и свойствами, которые доступные для использования всеми последующими;

- Два класса модулей Module и один View - выводит общую картину.


error_reporting(E_ALL);


class Chief
{
private static $obs = array();
private $classes = array(
'lib' => 'Library',
'mod1' => 'Module1',
'mod2' => 'Module2',
'view' => 'View',
);

public function __get($name)
{
// Определение имени классов в которых вызываются не определенные свойства
$descendantClassName = get_class($this);
echo $descendantClassName . '<br>';

// Если объект уже существует, возвращаем его
if(isset(self::$obs[$name]))
{
return(self::$obs[$name]);
}
// Определяем имя нужного класса
$class = $this->classes[$name];

// Сохраняем для будущих обращений к нему
self::$obs[$name] = new $class();

// Возвращаем созданный объект
return self::$obs[$name];
}
}

class Library extends Chief
{
// Свойства и методы библиотеки выполняющие что-либо, созданные для примера

public $prop_1;
public $prop_2;
public $prop_3;

public function __construct(){}

public function toolA(){}

public function toolB(){}

public function toolC(){}
}

class Module1 extends Chief
{
public function perf()
{
$this->lib->toolA();
$m2 = new Module2();
return $this->lib->prop_3 = $m2->perf();
}
}

class Module2 extends Chief
{
public function perf()
{
return $this->lib->toolC();
}
}

class View extends Chief
{
public function perf(){

$this->lib->toolB();
$content = new Module1();
$content->perf();
$this->lib->prop_1;
}
}

$res = new View();
print $res->perf();

Вопрос: нужно предавать объекту класса Library информацию о том в которых классах осуществляется его вызов, то есть переменную $descendantClassName.

Можно было б передать это параметром в конструкторе self::$obs[$name] = new $class($descendantClassName) и при создании объекта $this->lib использовать эту инфу. Но это возможно только 1 раз, при дальнейших вызовах объекта $this->lib он просто возвращается из массива с первоначально заложенным значением переменой $descendantClassName. Как тогда передавать классу Library постоянно меняющиеся данные из переменной $descendantClassName если возвращается уже созданный объект.

ДП
На сайте с 23.11.2009
Offline
203
#1


public function __get($name)
{
// Определение имени классов в которых вызываются не определенные свойства
$descendantClassName = get_class($this);
echo $descendantClassName . '<br>';

// Если объект уже существует, возвращаем его
if(isset(self::$obs[$name]))
{
self::$obs[$name]->calling_class = $descendantClassName;
return(self::$obs[$name]);
}
// Определяем имя нужного класса
$class = $this->classes[$name];

// Сохраняем для будущих обращений к нему
self::$obs[$name] = new $class();

// Возвращаем созданный объект
self::$obs[$name]->calling_class = $descendantClassName;
return self::$obs[$name];
}

Или какие-то такие костыли, или может с рефлексией заморочиться, или рассказать для чего вам это человеческим языком, а то похоже на проблему x y (http://7bloggers.ru/xy-problem/)

S
На сайте с 23.05.2004
Offline
316
#2

Позвольте поинтересоваться, а зачем такое надо, ООП ради ООП ?

Если из наследуемого класса вам нужно постоянно переопределять функцию или переменную, то лучше сделать не в наследуемом, а в основном классе.

Это просто подпись.
O
На сайте с 23.09.2014
Offline
76
#3
Дикий пионер:
Или какие-то такие костыли

В чем именно замечен костыль?

Возможно есть другое решение как передать данные в $this->lib. - дополнить эту структуру. Может существуют подходящие паттерны?

Aisamiery
На сайте с 12.04.2015
Offline
293
#4
Osavul:
В чем именно замечен костыль?

Возможно есть другое решение как передать данные в $this->lib. - дополнить эту структуру. Может существуют подходящие паттерны?

А что мешает реализовать магический метод __set?

Как то так:


public function __set($name, $value)
{

// Если объект уже существует, пытаемся пропихнуть свойство
if(isset(self::$obs[$name]))
{
self::$obs[$name]->setValue($value); // Реализуйте свой метод
return self::$obs[$name]; // Возвращаем для цепочки вызовов
}

// Если не существует, можно создать

// Определяем имя нужного класса
$class = $this->classes[$name];

// Сохраняем для будущих обращений к нему
self::$obs[$name] = new $class();

// Определение имени классов в которых вызываются не определенные свойства
$descendantClassName = get_class($this);
echo $descendantClassName . '<br>';

// Возвращаем созданный объект
self::$obs[$name]->calling_class = $descendantClassName;
self::$obs[$name]->setValue($value); // Реализуйте свой метод
return self::$obs[$name]; // Возвращаем для цепочки вызовов
}

Как то так вообщем.

P.S. Только фабрика у вас так себе получилась. Мой совет - курите GoF дальше

Разработка проектов на Symfony, Laravel, 1C-Bitrix, UMI.CMS, OctoberCMS
ДП
На сайте с 23.11.2009
Offline
203
#5
Osavul:
В чем именно замечен костыль?

Внутреннее чувство жопой, что если классу нужно знать имя вызывающего его класса - то это костыль.

И костылём я своё предложение называл.

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий