PHPで値型の構造クラスをエミュレート
-
18-09-2019 - |
質問
PHPで構造クラスをエミュレートする方法はありますか?すなわち、それはまだ種類が示唆されるように、値ではなく参照によって渡すクラス...
もしそうなら、何が違うの技術が使用されるだろうか?最高の技術は何ですか?
これが可能であるならば、あなたは明らかに完全にPHPのための安全な層を入力し作成することができ、そこにこのような層がありますか?誰もがこれでの経験があったか?
解決
オブジェクトは常に参照によって渡されます。彼らはコピーとして渡すようにする唯一の方法は、明示的に(はい、どこでも)clone
キーワードを使用することです。
私の推薦は、値型であり、したがって、常にコピー配列を使用することであろう。あなたが連想配列(例えば、文字列 - >値)として使用することができますので、それは同様のオブジェクトであるかもしれません。欠点は、あるもちろん、あなたがメソッドを使用することはできません(しかし、あなたはこれで幸せになることがありので、それは構造体のようなものです)。型の安全性を強制する方法はしかし、ありません。
しかし、PHP言語のあなたのようなものではありませんように、それは正直に言うと、鳴ります。
すべての要件と他のヒント
私は、最も簡単な方法は、Javaがないようにそれを行うことだと思う - あなたの値クラスは不変であり、すべての「変更」方法ではなく、新しいオブジェクトを返してみましょう。
。私はあなたが唯一のPHPコードで、その目標を達成することができないと思います。
あなたはどのようにPHPの関数ハンドルパラメータに制御することはできません、と私はあなたが必ずすべてがPHPバイナリとモジュールに(低レベル)のコードを変更することなく、あなたが望むように処理されていることを確認できる方法が表示されませんます。
これはしかし、かなりクールのようになります。)
私は、オブジェクトの任意の変異を作るために、匿名の提案で遊んでましたが、新しいオブジェクトを返し、これは動作しますが、それは厄介だ。
<?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';
最後に、それはおそらく変数をプライベートにして何のミューテーターを提供しない方が簡単ですので、変数の「列挙型」の値を変更する唯一の方法は、新しいものを作成するには、次のようになります。
echo $obj; // "banana"
$obj = new FruityEnum("cantaloupe");