LINUX.ORG.RU

Пыхопроблема

 , , ,


0

1

Есть такой тестовый код:

class a {

    protected $data = array();

    public function set($key, $value) {

        if (!array_key_exists($key, $this->data)) {
            $this->data[$key] = $value;
        }

    }

}


class b extends a {}
class c extends a {}


$b1 = new b();
$b2 = new b();
$b3 = new b();
$c1 = new c();
$c2 = new c();


$b1->set('x', 'b1x');
$b2->set('x', 'b2x');
$b3->set('x', 'b3x');
$c1->set('y', 'c1y');
$c2->set('y', 'c2y');

Пример сильно упрощен, на деле потомки тащат кучу зависимостей (всякие «статичные» данные) которые одинаковые потомки же и используют одинаково. Было бы хорошо эти данные сложить в общее место, попутно проверяя, если такой же потомок (в примере проверяется тупо по ключу) уже насрал своих данных в это общее место, то повторно не вызывать тучу говна, которое пойдет куда-то и будет получать эти данные заново.

В идеальном случае требуется такое поведение, чтобы эта $this->data была для всех классов-потомков глобальной.

Педалить еще одну сущность которая будет все это дело хранить? Блин, костыль же. А завтра мне понадобится аналогичное поведение в другом месте. Опять педалить дополнительную сущность?

Не понял сути проблемы. Нужны общие данные для всех классов? Тогда data нужно сделать static. Нужно упростить процесс инициализации? Можно присваивать сразу массив. Если что-то другое, распиши проблему точнее.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

data нужно сделать static

class a {

    protected static $data = array();

    public function set($key, $value) {

        if (!array_key_exists($key, parent::$data)) {
            parent::$ata[$key] = $value;
        }
        var_dump(parent::$data);

    }

}

Упс:

Fatal error:  Cannot access parent:: when current class scope has no parent
А вот если вместо parent пишем self, то вроде все нормально. А почему?

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

Каким вообще образом self ссылается на «общие» данные?

deep-purple ★★★★★
() автор топика

Блин, костыль же

Что? Ты сам то можешь расшифровать свой поток мысли?

no-such-file ★★★★★
()
Ответ на: комментарий от deep-purple

А вот если вместо parent пишем self, то вроде все нормально. А почему?

Ты доки по ООП читал?

ritsufag ★★★★★
()

Педалить еще одну сущность которая будет все это дело хранить? Блин, костыль же. А завтра мне понадобится аналогичное поведение в другом месте. Опять педалить дополнительную сущность?

Это еще почему? По-моему самое логичное решение. Можно конкретно задачу описать и сказать, почему такое решение не подходит? То, что может понадобиться такое же поведение где-то еще — не аргумент.

Kilte ★★★★★
()
Ответ на: комментарий от Kilte

Вобщем из БД достается некоторое кол-во записей, где каждая из них содержит какие-то данные. Этот массив я пробегаю циклом, в кажлой итерации беру значение поля type, это имя класса, где каждый класс должен добавить в какое-то место свои зависимости, но только один раз. Выглядит это примерно так:

foreach (db::query('SELECT ... ')->fetchAll(PDO::FETCH_ASSOC) as $item) {
    $className = $item['type'];
    $obj = new $className();
    // у каждого типа объекта свои зависимые данные
    // различия описаны в методе getDependencyData()
    // но в выборке типы повторяются
    // и хотелось бы не лезть повторно за данными, которых может быть много и доставать их долго
    // в самом результате выборки эти зависимые данные НЕ нужны
    // их потом единоразово нужно вывести совсем в другом месте
    $obj->getDependencyData();
}
deep-purple ★★★★★
() автор топика

Кароче ну его нахрен. Запилил глобально доступную хренатень, которая собирает эти высеры. А потом она же и возвращает в нужном месте все что собралось. Ибо лепить в родительском классе метод, который в хер не впился для потомков - мега-костыль. Глобальная хренатень хотябы вменяемо выглядит.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от anonymous

паттерн observer или что-то в этом роде

Название само за себя говорит )) Обсеря или что-то в этом роде. Меня вообще вся эта паттерно-хрень умиляет - запилил говнорешение на говноклассах, ООП ради ООП, надо как-то обозвать, почесать свое копирайтское эго.

О, а видал как Yii сделан, не? Там такой файлик есь yiilite.php ну типа лайт. Открываю я этот лайт, а там херова туча классов на более чем 10 тыщ строк кода. И это только один файл. А потом там есь жи этот импорт гамна из папки - так прям и пишут типа import('path/do/component/*') и меня эта звездочка в конце просто умиляет - а, ну да, давай подгрузим еще пол метра говна, которое может и не понадобиться во время выполнения.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

Какая-то странная фигня получается. Действительно необходимо создавать несколько экземпляров одного и того же класса при одинаковых данных? Хотя возможно, что есть еще какие-то нюансы. Ну не суть.

Возможно имеет смысл хранить эти данные статически или же более «правильнее» сделать коллекцию/фабрику (или как это правильнее назвать?) этих самых данных и в зависимости от конкретного класса возвращать эти данные.

Я бы предпочёл вынести все эти зависимости в какое-нибудь другое место. Т.е. получится что-то вроде этого:

class SomeItem1 {}
class SomeItem2 {}

class Dependencies {
   public function get($key) {
       if (is_object($key)) {
           $key = get_class($key);
       }
       // Здесь можно сделать так, чтобы для конкретного класса данные подтягивались единожды и при необходимости.
       if (array_key_exists($this->dependencies, $key)) {
           return $this->dependencies[$key];
       }
       throw new \RuntimeException('There are no dependencies for given object');
   }
}


$dependencies = new Dependencies(/* ... */);
foreach (db::query('SELECT ... ')->fetchAll(PDO::FETCH_ASSOC) as $item) {
    $className = $item['type'];
    $obj = new $className();
    $dependencies->get($className);
}

Ну а если такая штука понадобится где-то еще, то достаточно будет просто вынести общую логику в базовый класс и в него внедрять конкретные реализации, отвечающие за получение данных.

Kilte ★★★★★
()
Ответ на: комментарий от anonymous

По-моему это вообще тут не причём. Что тут обсёрвить?

Kilte ★★★★★
()
Ответ на: комментарий от Kilte

Действительно необходимо создавать несколько экземпляров одного и того же класса при одинаковых данных?

Не, тут понятно, что не нужно создавать повторно.

Вобщем я уже сделал, правда не совсем так как ты щас написал. Я просто запилил абстракт который глобально доступен, передаю ему $item->type а там он уже смотрит было, не было, и если не было, то дергает метод экземпляра который тащит депенденсы. А уже потом в нужном месте этот же абстракт возвращает все что насобиралось.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

Ну это уже совсем черезжопно. Глобально доступный класс только для того, чтобы дёрнуть нужный метод. Мугога. Я бы ни за что не додумался.

Неполенился и набросал более наглядный пример http://code.re/6vq

Kilte ★★★★★
()
Ответ на: комментарий от Kilte

На вкус и цвет.. По мне так черезжопным выглядит простыня с описанием нескольких интерфейсов и классов, создание экземпляров объектов для этих классов - и все только для того, чтобы единожды подгрузить данные для списка типов которые могут повторяться.

Согласишься же что: описание класса жрет память, а создание экземпляра тоже жрет память.

Вообще таки пример по ссылке, ну, типа «академический» - там усё правильно сделано.

Вот на работе я пишу так же (как барин скажет или как «модно») - обвязки наваляю - няхай крутится по 2-6 метров на скрипт (а если еще с тестами, то ваще память можно не считать), потом кеш прикрутим чо..

А для себя - мне оно не впилось сидеть выписывать картину маслом.

deep-purple ★★★★★
() автор топика

Не уверен, что понял, но, предполагая, что нужно что-то вроде кэширования запросов, если в PHP есть замыкания, можно аналог вот этого кода js


parent=function(allData){
return function(show){
if(arguments[0]) return console.log(allData)
return function(selfData){
return function(key, value){
if(selfData[key]) return
if(allData[key]) return
allData[key]=value
selfData[key]=value 
}
}({})
}
}({})

child1=parent()
child2=parent()

child1("one", 1)
child2("two", 2)
child2("one", 1)
parent("show me data")

И можно, если нужен ещ обект с таким же поведением, замутить «фабрику» родителей. Извиняюсь, если спорол х*ню, не совсем понял, что нужно.

linux-101
()
Ответ на: комментарий от linux-101

Да это ж то же самое что мы тут выше обсуждали.

У меня вопрос был как сделать без дополнительных сущностей, фабрик-шмабрик. Народ начал предлагать варианты со шмабриками.

Кронос подсказал сделать статик и дописать метод в родителя. Но тут выходит что потомки получают ссылку на нахрен не нужные им методы родителя - так есть шанс что чьи-то шаловливые ручки (пусть и только мои) случайно вызовут эти методы в контексте потомка, а не парента - будет гамно. А переопределять у каждого потомка методы дабы заглушить обращение к паренту - тоже гамно.

ООП в пхп - страшное костыляторство. А если учесть что оно слизано с жав и прочего - то все ООП - есь страшное гамно. И все эти паттерны - жопа с ручкой. ООП ради ООП. Гимна не хватает.

В любом случае я уже запилил сущность которая собирает и хранит данные.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

ООП в пхп - страшное костыляторство.

а между тем ты даже не прочитал документацию к parent и self и после этого задаешь такие вопросы:

А вот если вместо parent пишем self, то вроде все нормально. А почему?

читай документацию - мать твою! там всё написано!

stevejobs ★★★★☆
()
Ответ на: комментарий от stevejobs

Ты как-то слишком быстро ответил, надо было через пол года придти написать. На свой вопрос «почему» я получил ответ в документации через минуту после того как запостил ту мессагу. Именно потому проигнорил ответы выше с тем же смыслом как и твой.

По делу то есть что?

deep-purple ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.