- assert: documentation ( source)
- var_dump: documentation ( source)
- spl_object_hash: documentation ( source)
<?php
function hashcode($str){
// return sha1($str);
return $str;
}
class SomethingBuilder
{
private $name;
private $super;
function __construct($name){
$this->name = $name;
}
function getName(){
return $this->name;
}
function setSuper(SomethingBuilder $super = null){
$this->super = $super;
}
function getSuper(){
return $this->super;
}
function getHash(){
return hashcode("\\SomethingBuilder|" . spl_object_hash($this));
}
function equals($other){
return $this->getHash() === $other->getHash();
}
}
class Something
{
protected $super;
protected $name;
function __construct(SomethingBuilder $builder){
$this->name = $builder->getName();
$argBuilder = $builder;
$immutables = [];
$builders = [];
do{
if(isset($immutables[$builder->getHash()])) break;
// this should rather be a private class, which php doesn't have yet, but better than nothing.
$immutable = $builder === $argBuilder ? $this : new class($builder->getName()) extends Something{
function __construct($name){
$this->name = $name;
}
};
$immutables[$builder->getHash()] = $immutable;
$builders[$builder->getHash()] = $builder;
}while($builder = $builder->getSuper());
foreach($immutables as $builderHash => $immutable){
$immutable->super = $immutables[$builders[$builderHash]->getSuper()->getHash()];
}
}
function getName(){
return $this->name;
}
function getSuper(){
return $this->super;
}
function getHash($origin = null){
if($this === $origin){
return hashcode("*RECURSION*");
}else{
return hashcode(
"Something" .
"{" .
$this->getName() .
"|" . $this->getSuper()->getHash($origin ?? $this) .
"}"
);
}
}
function equals($other){
return $this->getHash() === $other->getHash();
}
}
$a = new SomethingBuilder("A");
$b = new SomethingBuilder("B");
$c = new SomethingBuilder("C");
$a->setSuper($c);
$b->setSuper($a);
$c->setSuper($b);
$immutable = new Something($a);
var_dump($immutable->getHash());
var_dump($immutable->getSuper()->getHash());
var_dump($immutable->getSuper()->getSuper()->getHash());
var_dump($immutable->getSuper()->getSuper()->getSuper()->getHash());
var_dump($immutable->getSuper()->getSuper()->getSuper()->getSuper()->getHash());
assert($immutable === $immutable->getSuper()->getSuper()->getSuper());
assert(
$immutable->equals(
$immutable->getSuper()->getSuper()->getSuper()
)
);
echo "\n\n";
$a = new SomethingBuilder("A");
$a->setSuper($a);
$immutable = new Something($a);
var_dump($immutable->getHash());
var_dump($immutable->getSuper()->getHash());
assert($immutable === $immutable->getSuper());
assert($immutable->equals($immutable->getSuper()));