<?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()));
- Output for 7.0.0 - 7.0.20, 7.1.0 - 7.1.33, 7.2.0 - 7.2.33, 7.3.0 - 7.3.33, 7.4.0 - 7.4.33, 8.0.0 - 8.0.30, 8.1.0 - 8.1.28, 8.2.0 - 8.2.18, 8.3.0 - 8.3.6
- string(50) "Something{A|Something{C|Something{B|*RECURSION*}}}"
string(50) "Something{C|Something{B|Something{A|*RECURSION*}}}"
string(50) "Something{B|Something{A|Something{C|*RECURSION*}}}"
string(50) "Something{A|Something{C|Something{B|*RECURSION*}}}"
string(50) "Something{C|Something{B|Something{A|*RECURSION*}}}"
string(24) "Something{A|*RECURSION*}"
string(24) "Something{A|*RECURSION*}"
- Output for 5.4.2 - 5.4.45, 5.5.24 - 5.5.35, 5.6.8 - 5.6.28
- Parse error: syntax error, unexpected 'class' (T_CLASS) in /in/01OF4 on line 52
Process exited with code 255.
preferences:
197.06 ms | 402 KiB | 272 Q