Вопрос

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

И если да, то какие различные методы можно было бы использовать?Какая техника самая лучшая?

Если это возможно, вы, очевидно, могли бы создать полностью типобезопасный слой для PHP, существуют ли такие слои?Был ли у кого-нибудь какой-нибудь опыт в этом?

Это было полезно?

Решение

Объекты всегда передаются по ссылке.Единственный способ заставить их передаваться как копия - это явно использовать clone ключевое слово (да, везде).

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

Но, честно говоря, учитывая все ваши требования, похоже, что PHP - это не ваш тип языка.

Другие советы

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

Я не думаю, что вы можете достичь этой цели, только с помощью PHP-кода.

У вас нет контроля над тем, как функции PHP обрабатывают параметры, и я не понимаю, как вы могли бы убедиться, что все обрабатывается так, как вы хотите, без необходимости изменять (низкоуровневый) код в двоичном коде PHP и модулях.

Хотя это было бы довольно круто :)

Я поиграл с предложением anonymous заставить любые мутации объекта возвращать новый объект, и это работает, но это неудобно.

<?php
class FruityEnum {
    private $valid = array("apple", "banana", "cantaloupe");
    private $value;

    function __construct($val) {
        if (in_array($val, $this->valid)) {
            $this->value = $val;
        } else {
            throw new Exception("Invalid value");
        }
    }

    function __set($var, $val) {
        throw new Exception("Use set()!!");
    }
    function set(FruityEnum &$obj, $val) {
        $obj = new FruityEnum($val);
    }

    function __get($var) { //everything returns the value...
        return $this->value;
    }
    function __toString() {
        return $this->value;
    }
}

А теперь, чтобы проверить это:

function mutate(FruityEnum $obj) { // type hinting!
    $obj->set($obj, 'banana');
    return $obj;
}

$x = new FruityEnum('apple');
echo $x; // "apple"
$y = mutate($x);
echo  $x // still "apple"
    . $y // "banana"

Это работает, но вам приходится использовать странный способ изменения объекта:

$obj->set($obj, 'foo');

Единственный другой способ, который я мог придумать, чтобы сделать это, было бы использовать __set() метод, но это было еще хуже.Ты должен был это сделать, что чертовски сбивает с толку.

$obj = $obj->blah = 'foo';

В конце концов, вероятно, проще сделать переменные закрытыми и не предоставлять мутаторов, поэтому единственным способом изменить значение переменной "enum" было бы создать новое:

echo $obj; // "banana"
$obj = new FruityEnum("cantaloupe");
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top