Skip to content

Instantly share code, notes, and snippets.

@Rican7
Created July 28, 2017 19:49
Show Gist options
  • Save Rican7/5b5c4c770b1e3b6a270c33a92e249a51 to your computer and use it in GitHub Desktop.
Save Rican7/5b5c4c770b1e3b6a270c33a92e249a51 to your computer and use it in GitHub Desktop.
PHP Strongly Typed Object Set
<?php
declare(strict_types=1);
interface Set extends Countable, IteratorAggregate
{
public function add(...$members): void;
public function remove(...$members): void;
public function contains(...$members): bool;
public function clear(): void;
public function toArray(): array;
}
final class Foo
{
private $value;
public function __construct(int $value)
{
$this->value = $value;
}
public function value(): int
{
return $this->value;
}
}
final class FooSet implements Set
{
private $set;
public function __construct(Foo ...$members)
{
$this->set = new class() extends SplObjectStorage
{
public function getHash($member): string
{
return (string) $member->value();
}
};
$this->add(...$members);
}
public function add(...$members): void
{
$this->ensureValidType(...$members);
foreach ($members as $member) {
$this->set->attach($member);
}
}
public function remove(...$members): void
{
$this->ensureValidType(...$members);
foreach ($members as $member) {
$this->set->detach($member);
}
}
public function contains(...$members): bool
{
if (1 > count($members)) {
return false;
}
$this->ensureValidType(...$members);
return array_reduce(
$members,
function (bool $contains, Foo $member) {
return $contains && $this->set->contains($member);
},
true
);
}
public function clear(): void
{
$this->set->removeAll($this->set);
}
public function toArray(): array
{
// There's probably a more efficient way of doing this...
return iterator_to_array($this->set, false);
}
public function count(): int
{
return $this->set->count();
}
public function getIterator(): Iterator
{
return new class($this->set) extends IteratorIterator
{
public function current(): Foo
{
return parent::current();
}
};
}
private function ensureValidType(Foo ...$members): void
{
return;
}
}
$set = new FooSet(new Foo(1), new Foo(2));
$set->add(new Foo(3), new Foo(4));
var_dump(
count($set),
$set->contains(new Foo(1)),
$set->contains(new Foo(99999)),
$set->remove(new Foo(1), new Foo(4)),
count($set),
$set->contains(new Foo(1)),
$set->toArray()
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment