Created
October 22, 2012 13:27
-
-
Save mrclay/3931502 to your computer and use it in GitHub Desktop.
Generics in PHP experiment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require __DIR__ . '/TypedList.php'; | |
class Foo {} | |
$list = new MrClay\Generics\TypedList('Foo'); | |
/* @var Foo[] $list */ | |
$list[] = new Foo(); | |
$list[] = new stdClass(); // exception at run-time, but better than nothing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace MrClay\Generics; | |
use Exception; | |
use InvalidArgumentException; | |
class TypedList extends \SplDoublyLinkedList | |
{ | |
/** | |
* @var string | |
*/ | |
protected $type; | |
/** | |
* @param $type string|array | |
* | |
* @throws InvalidArgumentException | |
*/ | |
public function __construct($type = null) | |
{ | |
if (is_string($type)) { | |
$this->setType($type); | |
} elseif (is_array($type)) { | |
if (empty($type)) { | |
throw new InvalidArgumentException('$type cannot be empty'); | |
} | |
foreach ($type as $val) { | |
$this->push($val); | |
} | |
} else { | |
throw new InvalidArgumentException('$type must be a class/interface name, or non-empty array of objects'); | |
} | |
} | |
/** | |
* @param string $type | |
* | |
* @throws Exception | |
*/ | |
public function setType($type) | |
{ | |
if (! $this->type || ($this->type === $type)) { | |
$this->type = $type; | |
} else { | |
throw new Exception('Once set, type cannot be changed'); | |
} | |
} | |
/** | |
* @return string | |
*/ | |
public function getType() | |
{ | |
return $this->type; | |
} | |
/** | |
* @param object $val | |
* | |
* @throws \InvalidArgumentException | |
*/ | |
protected function verifyType($val) | |
{ | |
if ($this->type) { | |
if (! $val instanceof $this->type) { | |
throw new InvalidArgumentException('Given value is not an instance of ' . $this->type); | |
} | |
} else { | |
if (!is_object($val)) { | |
throw new InvalidArgumentException('TypedArray can only accept objects'); | |
} | |
$this->type = get_class($val); | |
} | |
} | |
public function push($value) | |
{ | |
$this->verifyType($value); | |
parent::push($value); | |
} | |
public function unshift($value) | |
{ | |
$this->verifyType($value); | |
parent::unshift($value); | |
} | |
public function offsetSet($index, $value) | |
{ | |
$this->verifyType($value); | |
parent::offsetSet($index, $value); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment