Примитивные объекты

Духовность™

Продвинутый новичок
Примитивные объекты

Есть некая обертка-хранилище для переменных, реализация интерфейса ArrayAccess. Но не суть важно. Задача обертки - содержать в себе данные, уметь считать их, отдавать, в т.ч. null когда запрашивается undefined значение. Работает так:
PHP:
$get = new ArrayAccessImpl();
$get['a']['1'] = '00001';
$get['a']['2'] = '00002';

print_r($get);
/*
ArrayAccessImpl Object
(
    [data:protected] => Array
        (
            [a] => ArrayAccessImpl Object
                (
                    [data:protected] => Array
                        (
                            [1] => 00001
                            [2] => 00002
                        )
                )
        )
)
*/

var_dump($get['a']['undefined']); // создается и возвращается пустой объект-обертка

echo $get['a']['undefined']; // выведется пустая строка

echo $get['a']->count(); // 3
echo $get['a']->clear(); // очищаем 
echo $get['a']->count(); // 0
Решил я сделать такую фишку для обертки, когда при запрашивании скаляра, его можно было бы транслировать в любой тип
PHP:
$get = new ArrayAccessImpl();
$get['a']['b'] = '00001';
echo $get['a']['b']->asString(); // 00001
echo $get['a']['b']->asInt(); // 1
print_r($get['a']['b']->asArray()); // Array ( [0] => 00001 ) 
print_r($get['a']['b']->asHash()); // Array ( [b] => 00001 )
т.е. при запросе переменной из хранилища создавался бы объект "переменная" вот такого класса:
PHP:
class _Var
{
    private $var;
    private $key;

    public function __construct($var=null, $key=null)
    {
        $this->var = $var;
        $this->key = $key;
    }

    public function asInt()
    {
        return intval($this->var);
    }

    public function asString()
    {
        return strval($this->var);
    }

    // По умолчанию выводим как строку
    public function __toString()
    {
        return strval($this->var);
    }

    public function asBool()
    {
        return (boolean)$this->var;
    }

    public function asArray()
    {
        return (array)$this->var;
    }

    public function asHash()
    {
        return array($this->key => $this->var);
    }

    // далее можно придумать кучу полезных методов 
}
как вам идея? не накладно ли при каждом запросе переменной из хранилища создавать объект _Var?

-~{}~ 29.07.09 18:08:

UPD: КОД
 

phprus

Moderator
Команда форума
Мне это напоминает Variant из boost или QVariant из Qt (http://doc.qtsoftware.com/4.5/qvariant.html).
Но вот только я не пойму, зачем создавать такое в языке с динамической типизацией, где реальный тип переменной можно узнать?
 

korchasa

LIMB infected
ИМХО тут перебор не стороны накладности, а со стороны соглашений по формату данных, что ли. Т.е. то, что ты используешь ArrayAccess как бэ говорит нам, что ты хочешь чтобы пользователь пользовался интерфейсом родного типа - массива. А в конце, внезапно, получается объект. ИМХО, набор кастующих (по твоим правилам) функций был бы логичнее.
 

phprus

Moderator
Команда форума
triumvirat
Сразу уточню, что я говорю про class _Var.

Я имел ввиду семейства функций is_*, оператор instanceof.
В PHP если мы получили какую-либо переменную $var, то мы сможем узнать какого она типа(или что об этом типе думает интерпретатор) и привести ее к нужному нам типу.
В компилируемых языках так сделать не получится. В том-же С++ имея void *var мы никогда не сможем узнать что-же на самом деле в ней хранится. Кроме того в PHP мы легко сможем создать массив, который будет содержать элементы разных типов, а в С++ такое сделать нельзя.
По этому в С++ для хранения переменных с заранее неизвестным типом или для хранения переменных разного типа в одном контейнере приходится использовать шаблон проектирования Variant.

По этому я и не понимаю зачем дублировать функциональность самого PHP классом _Var?
 

Духовность™

Продвинутый новичок
ArrayAccess как бэ говорит нам, что ты хочешь чтобы пользователь пользовался интерфейсом родного типа - массива. А в конце, внезапно, получается объект
что есть, то есть
PHP:
$get = new ArrayAccessImpl();
$get['a'] = array(11, 22, 33);

echo ( 1 + $get['a'][0]->asInt() ); // только с помощью ->asInt()
-~{}~ 29.07.09 18:33:

По этому я и не понимаю зачем дублировать функциональность самого PHP классом _Var?
чисто для удобства форматирования переменных и их представления.
 

no_santa

Снегур
triumvirat Направление знакомое... будь осторожен - так можно и к питону придти, а это опасно! :)

По крайней мере, я вляпался по самые помидоры и не жалею об этом, особенно в плане... (далее вырезано цензурой, т.к. является рекламой питона...) ;)
 

phprus

Moderator
Команда форума
чисто для удобства форматирования переменных и их представления.
Чем intval($var) лучше $var->asInt()? Во втором случае мы в довесок получаем лишние вызовы php'шных функций, а это лишнее время.
Ты не пробовал замерять на сколько пострадает производительность если все переменные в какой-либо серьезной программе обернуть в класс _Var?

// только с помощью ->asInt()
Скажи пожалуйста, ты случайно не ставишь целью этого решения запретить везде неявные преобразования типов и перейти к использованию только as*()-методов?
Если такая цель тоже есть то применимость данного решения понятна.

Скажи пожалуйста, а как оно расширяется на хранение объектов произвольных, неизвестных в момент написания кода класса _Var, пользовательских классов?
 

AmdY

Пью пиво
Команда форума
echo ( 1 + $get['a'][0]->asInt() );
здесь ни asInt, ни intval не нужно, пых сам всё сделает, сразу к int, затем к string.

и уж если делать, то единообразно, а то действительно зоопарк получается
$get->get('a')->get(0)->asInt()
 

Духовность™

Продвинутый новичок
Ты не пробовал замерять на сколько пострадает производительность если все переменные в какой-либо серьезной программе обернуть в класс _Var?
нет

Скажи пожалуйста, ты случайно не ставишь целью этого решения запретить везде неявные преобразования типов и перейти к использованию только as*()-методов?
+ иметь возможность преобразовывать типы с учетом моих требований. сделать массу методов as*() и ими оперировать.

Скажи пожалуйста, а как оно расширяется на хранение объектов произвольных, неизвестных в момент написания кода класса _Var, пользовательских классов?
хз

тогда _Var можно выкинуть... зачем он тогда?

....
 

AmdY

Пью пиво
Команда форума
кстати, автокомплит работать не будет с []
сам набрасывал подобную штуку для шаблонизатора, но затем решил, что она бессмысленна и выбросил. разве что для избавления от isset, чтобы по get возвращалась заглушка(не null) с магией __get, __call, __toString.
 

Духовность™

Продвинутый новичок
Усложняет жизнь на самом деле отсутствие примитивных объектов типов как в JS и возможность их расширения через дополнительный функционал.

-~{}~ 30.07.09 12:03:

Ты не пробовал замерять на сколько пострадает производительность если все переменные в какой-либо серьезной программе обернуть в класс _Var?
:(

операция с 10 000 переменных на чистом PHP - 0.5 сек без всех этих классов
С оберткой ArrayAccessImpl - 3 сек

С _Var - 5 секунд
 

phprus

Moderator
Команда форума
triumvirat
Усложняет жизнь на самом деле отсутствие примитивных объектов типов как в JS и возможность их расширения через дополнительный функционал.
Просто у PHP другая идеология построения всего. Так-же можно сказать и про другие языки, что язык А не умеет делать что-то что умеет язык Б. Но может быть раз не умеет, то это и не нужно?
В JS возможность вносить изменения во строенные объекты может приводить к конфликтам библиотек.
 

Духовность™

Продвинутый новичок
Дя, я уже это осознал... Жаль.

Всем спасибо. Вопрос закрыт. От класса-обертки переменной пришлось отказаться.
 
Сверху