Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php declare(strict_types=1);
- namespace tests\unit;
- use BadMethodCallException;
- class Immutable
- {
- private $a;
- private $b;
- private $c;
- protected $set = false;
- /**
- * Returns an instance clone that is now immutable, further calls to with<Name> wiill return clones
- * @throws BadMethodCallException if already set
- */
- public function set(): Immutable
- {
- if ($this->set) {
- throw new BadMethodCallException("Instance is already set!");
- }
- $new = clone $this;
- $new->set = true;
- return $new;
- }
- public function isHard(): bool { return $this->set; }
- private function with(string $name, $value): Immutable
- {
- $new = $this->set ? clone $this : $this;
- $new->{$name} = $value;
- return $new;
- }
- public function withA(string $value): Immutable { return $this->with('a', $value); }
- public function withB(string $value): Immutable { return $this->with('b', $value); }
- public function withC(string $value): Immutable { return $this->with('c', $value); }
- public function __toString() { return "{$this->a} : {$this->b} : {$this->c}"; }
- }
- class ImmutableTest extends \PHPUnit\Framework\TestCase
- {
- public function testThatDemonstrateUseCase()
- {
- // Semi builder pattern, but without needless instance generation
- $blank = (new Immutable)
- ->withA('Alpacca') // update $blank
- ->withC('Whool') // update $blank
- ->set() // $blank is from now on immutable
- ;
- $one = $blank->withB('Cool');
- $two = $blank->withB('Warm');
- $this->assertTrue($blank->isHard());
- $this->assertTrue($one->isHard());
- $this->assertTrue($two->isHard());
- $this->assertNotSame($blank, $one);
- $this->assertNotSame($blank, $two);
- $this->assertNotSame($one, $two);
- $this->assertEquals("Alpacca : : Whool", $blank);
- $this->assertEquals("Alpacca : Cool : Whool", $one);
- $this->assertEquals("Alpacca : Warm : Whool", $two);
- }
- public function testUndefined()
- {
- $this->expectException(BadMethodCallException::class);
- $this->expectExceptionMessage("Instance is already set");
- $c = (new Immutable)->set()->withA('a')->set();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement