возможно ли создать константный объект?

domino

Новичок
возможно ли создать константный объект?

возможно ли создать объект класса, свойства которого нельзя было бы изменять?

допустим, класс A имеет переменную public $a=5;
можно ли создать аналог того, что в С++ называется константный объект? const obj = new A; ?
define принимает только скалярные аргументы. а const может быть использован только внутри класса.
но может как-то можно извратиться через eval - что-то в духе - создания аналогичного класса на лету, свойства которого доступны только для чтения?
 

zerkms

TDD infected
Команда форума
создай статический метод/функцию, которые возвращают всегда один и тот же объект и пусть тот объект через __get отдаёт свойства только на чтение.
 

domino

Новичок
спасибо. щас попробую

-~{}~ 04.05.09 07:28:

2 zerkms: я тупой наверное. ну и что, что он статик? ок, при втором вызове объект возвращается в первоначальном виде, но всё равно его свойства можно менять со свистом. он от этого не становится константным. если не сложно, покажи на примере, что ты имел ввиду.
 

fixxxer

К.О.
Партнер клуба
PHP:
class foo {
    protected $foo=1, $bar=2;
    function __get($k) {
        if (isset($this->$k)) 
            return $this->$k;
        else
            throw new RuntimeException("Undefined property: $k"); // или return null если так больше нравится
    }
}
обернуть в статик по вкусу
 

domino

Новичок
2 fixxxer: я не об этом спрашивал ) я спрашивал как создать константный объект и возможно ли это.

возможно ли создать константный объект класса: class A { public $a=1; } ?
 

zerkms

TDD infected
Команда форума
domino
перечитай внимательно тред. от начала до конца.
если ты не понял кода фиксера - обратись в документацию по __get() или спрашивай вопросы конкретно по коду.
если ты не удовлетворён ответом - тогда задавай вопрос ещё раз, с нормальным описанием целей-задач.

краткая резолюция: as is в пхп константных объектов нет.
 

Gorynych

Посетитель PHP-Клуба
domino в чем смысл "константного объекта"? В сложной структуре данных, которую вы пытаетесь получить гарантировано не измененной в любом произвольном месте программы или в том, чтобы перенести ту или иную возможность синтаксиса из одного языка в другой?
 

domino

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

2 zerkms: ок. я не понял код. __get возвращает свойства класса определённым образом. действительно, если в классе нет паблик свойств, то мы сможем их читать и не сможем менять. но если в классе есть паблик переменные?
 

zerkms

TDD infected
Команда форума
2 zerkms: ок. я не понял код. __get возвращает свойства класса определённым образом. действительно, если в классе нет паблик свойств, то мы сможем их читать и не сможем менять. но если в классе есть паблик переменные?
при решении нужно отталкиваться от задачи, а не решение притягивать за уши к условиям.
какая у тебя задача? сделать RO свойства? ну так сделай их через __get() и никаких public. ы?
 

dimagolov

Новичок
domino, ты подтяжки носишь? просто исходя из того, что ты не доверяешь себе и думаешь, что где-то напишешь код, который залезет в объект и что-то в нем поменяет "когда не надо", то должен не доверять и своим штанам...
 

Духовность™

Продвинутый новичок
но если в классе есть паблик переменные?
Магические методы предоставляют интерфейс для манипулирования данными класса. Мы можем не создавать никаких паблик свойсв, а иметь private/protected хранилище, которое будет только отдавать существующие члены класса и не позволять их перезаписывать:

PHP:
class foo
{
    protected $data = array();

    public function __construct(){}

    public function __get($k)
    {
        if (isset($this->data[$k]))
            return $this->data[$k];
        else
            throw new Exception("Undefined property: $k"); // или return null если так больше нравится
    }

    public function __set($k, $v)
    {
        if (!isset($this->data[$k]))
        {
            $this->data[$k] = $v;
        }
        else
        {
            // или перезаписать, если так нравится
            throw new Exception("Попытка перезаписать свойство $k"); 
        }
    }
}

$storage = new foo();
$storage->a = 1;
$storage->b = 2;

echo $storage->a.' '.$storage->b;  // выведет 1 2

try {
    $storage->b = 'oter value';
}
catch (Exception $e)
{
   echo $e->getMessage(); // выведет Попытка перезаписать свойство b
}
 

Lightning

Трудоголик
возможно ли создать константный объект класса: class A { public $a=1; } ?
Нет.

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

PHP:
class foo
{
    protected $data = array();
    protected $constant_mode;

    public function __construct($data, $constant_mode = false) {
         $this->data = $data;
         $this->constant_mode = $constant_mode;
    }

    public function __get($name)
    {
        if (isset($this->data[$name]))
            return $this->data[$name];
        else
            throw new Exception("Undefined property: $name");
    }

    public function __set($name, $value)
    {
        if($constant_mode) {
             throw new Exception("Attempt to set property $name of constant object");
        }
        $this->data[$name] = $value;
    }
}

//...

$my_foo = new foo($data); //нормальный объект
$my_foo = new foo($data, true); //"константный" объект
-~{}~ 05.05.09 00:08:
dimagolov
просто исходя из того, что ты не доверяешь себе и думаешь, что где-то напишешь код, который залезет в объект и что-то в нем поменяет "когда не надо", то должен не доверять и своим штанам...
Ты никогда не допускаешь ошибок? Ты всегда с первого раза пишешь правильный код? Тебе не нужна ни отладка, ни тесты? Ты гений с феноменальными способностями?
 

dimagolov

Новичок
Ты никогда не допускаешь ошибок? Ты всегда с первого раза пишешь правильный код? Тебе не нужна ни отладка, ни тесты? Ты гений с феноменальными способностями?
Нет. Но изменение объекта, которые не нужно менять это логическая ошибка и придумывать синтаксический сахар чтобы отловить ее средствами языка ИМХО излишне. Достаточно выделить "опасные методы" такого объекта и сделать их search по проекту, чтобы выяснить где они вызываются. А используя их в коде все-таки думать о том, что ты делаешь, а не расчитывать на то, что нетерпретатор не позволит сделать глупость.
 

Lightning

Трудоголик
это логическая ошибка и придумывать синтаксический сахар чтобы отловить ее средствами языка ИМХО излишне
А я считаю, что отлавливать логические ошибки средствами языка не излишне. Стив Макконнелл, Джон Бентли и множество других разработчиков считают также.
Если тебе нравиться, когда поиск логических ошибок превращается в геморой, это не значит, что те, кому это не нравиться, носят подтяжки.
 

dimagolov

Новичок
Lightning, ты посмотри как ТС сформулировал вопрос. "константный объект". Скорее всего, для того, чтобы не наступать на те грабли, которых опасается ТС, есть более здоровые решения, чем "константный объект" реализованный через сеттеры. на 99.9% ему нужны просто приватные свойства и набор get методов для доступа к ним из других объектов.
 

Lightning

Трудоголик
dimagolov
Скорее всего, для того, чтобы не наступать на те грабли, которых опасается ТС,
на 99.9% ему нужны просто приватные свойства и набор get методов для доступа к ним из других объектов.
Мне начинает казаться, что ты предвзято относишься ко всем, у кого мало сообщений на форуме. Думаешь, что ТС - такой ламер, что вместо класса с геттерами будет использовать константный объект?
Он пишет:
возможно ли создать объект класса, свойства которого нельзя было бы изменять?

допустим, класс A имеет переменную public $a=5;
можно ли создать аналог того, что в С++ называется константный объект? const obj = new A; ?
Т.е. в общем случае свойства объекта класса A можно изменять, а в некоторых частных случаях - нельзя (константный объект).
На этот вопрос я и отвечал. Или я неправильно его понял?
 

dimagolov

Новичок
ну он то пишет по непониманию того, что переменная эта не должна быть public, раз она устанавливается в конструкторе и больше меняться не должна. и public/private/protected именно для того и существуют как базовые механизмы ООП.

а вот ты пишешь ерунду на тему
Т.е. в общем случае свойства объекта класса A можно изменять, а в некоторых частных случаях - нельзя (константный объект).
во-первых задача высосана из пальца и никакого реального смысла не имеет, как и отношению к вопросу. во-вторых чем тебе поможет твой constant_mode, если ты забудешь создать в нем объект с тем же успехом, что и случайно полезешь менять его?

-~{}~ 04.05.09 18:47:

Мне начинает казаться, что ты предвзято относишься ко всем, у кого мало сообщений на форуме.
совсем нет. просто когда такие личности "хотят странного", а данная тема как раз и этой оперы, то почти всегда они просто не знают как реализовать то, что надо по-людски и для того, чтобы не советовать ерунды надо или спросить или угадывать, зачем это ТС надо, чтобы узнать реальную задачу, а не криво придуманный способ ее решения, за реализацией которого ТС обратился на форум.
 

Lightning

Трудоголик
а вот ты пишешь ерунду на тему

Т.е. в общем случае свойства объекта класса A можно изменять, а в некоторых частных случаях - нельзя (константный объект).
const obj = new A(...); // константа, свойства менять нельзя
//...
A my_obj = new A(...); //переменная, свойства можно менять

ну он то пишет по непониманию того, что переменная эта не должна быть public, раз она устанавливается в конструкторе и больше меняться не должна.
совсем нет. просто когда такие личности "хотят странного", а данная тема как раз и этой оперы, то почти всегда они просто не знают...
Я вижу, что дальнейшая дискуссия бесполезна.
 

findnext

Новичок
domino
PHP:
class Foo{
	
  private $variables = array();
	
	function set($key, $var ) {
		
          if (isset($this->variables[$key]) == true) {
			
            throw new Exception('Unable to set `' . $key . '`. Already set.');
		
          }

          $this->variables[$key] = $var;

          return true;

       }

	function get($key) {
		
           if (!array_key_exists($this->variables[$key])) {
	   
             return null;
           
           }
		
           return $this->variables[$key];
	
        }

	function remove($var) {
		
           unset($this->variables[$key]);
	
        }
}
 
Сверху