PHP 仅包含特定 class 对象的数组
PHP array with only objects of a specific class
我有一个名为 Rule 的 class,我将要创建一个 RuleContainer class,它实际上是 Rule 对象数组。
我想知道是否有创建新 class 的替代方法。有什么(现代)方法可以解决这个问题吗?也就是说,类似于使用 SPL 定义 一个只允许添加特定 class.
对象的数组
如果不是,我应该在我的 RuleContainer 中实现哪个接口 class?
在你的情况下,我会实施 Iterator
interface in the RuleContainer
, as I've done several times when I needed a sort of Collection<T>
as we know it from other (typed) languages. And in the add(Rule $item)
or addItem(Rule $item)
method I'd make sure with the type definition of the argument (or using instanceof
) 要添加的项目的类型 Rule
。
最适合您任务的 class 是 SplObjectStorage
,但它不允许 class 类型提示。
我想,你可以这样做:
class RuleContainer extends SplObjectStorage
{
function attach(Rule $rule)
{
parent::attach($rule);
}
function detach(Rule $rule)
{
parent::detach($rule);
}
}
等等。您可以阅读 php.net
上的 SplObjectStorage
界面并决定您将使用什么以及需要覆盖什么。
根据容器的使用模式class,您需要实现以下接口中的一个或多个:
Iterator
- 将其用作 foreach($container as $key => $value)
;
Countable
- 对于 count($container)
;
ArrayAccess
- for $container[$key]
(设置它,得到它,检查它是否isset()
,unset()
它);
PHP 数组例程接口的使用
您可以实现您的目标,例如,ArrayAccess
implementation. Together with Iterator
它看起来像:
class ArrayStorage implements Iterator, ArrayAccess
{
private $holder = [];
private $instanceName;
public function __construct($instanceName)
{
if (!class_exists($instanceName)) {
throw new \Exception('Class '.$instanceName.' was not found');
}
$this->instanceName = $instanceName;
}
public function rewind()
{
reset($this->holder);
}
public function current()
{
return current($this->holder);
}
public function key()
{
return key($this->holder);
}
public function next()
{
next($this->holder);
}
public function valid()
{
return false !== $this->current();
}
public function offsetSet($offset, $value)
{
if (!($value instanceof $this->instanceName)) {
throw new \Exception('Storage allows only '.$this->instanceName.' instances');
}
if (is_null($offset)) {
$this->holder[] = $value;
} else {
$this->holder[$offset] = $value;
}
}
public function offsetExists($offset)
{
return isset($this->holder[$offset]);
}
public function offsetUnset($offset)
{
unset($this->holder[$offset]);
}
public function offsetGet($offset)
{
return isset($this->holder[$offset]) ? $this->holder[$offset] : null;
}
}
进程数
所以 - 是的,您正在明确地进行 instanceof
检查,但是 class 的最终用户并不知道这一点。只能在此存储的上下文中对有效实例进行操作(您可以查看 this fiddle 以获取使用示例)。概念是这样的:
$storage = new ArrayStorage('Foo'); //define what we will accept
$storage[] = new Foo; //fine, [] array-writing
$storage['baz'] = new Foo; //fine, key set
foreach ($storage as $key => $value) {
echo($key. ' => '.PHP_EOL.var_export($value, 1).PHP_EOL);
}
//invalid, will not pass. Either throw exception or just ignore:
$storage['bee'] = new Bar;
结束失败检查行为由您决定,但我认为,抛出异常是这里的最佳选择,因为它们是可捕获的,因此,最终用户可以决定在这种情况下要做什么。进一步的选择可能是将 Countable
添加到存储中,但它不会改变一般想法。
缺点
缺点 - 不,您将无法 "typehint" 它以某种方式。虽然它很有用,但在文档块中您仍然需要显示您接受哪种实体。在通用语言特性方面,Joe Watkins 提出了 arrayof RFC,它是为 PHP 5.6 版提出的,但不幸的是,它失败了。可能会在下一个版本中重新考虑。
您可以自己制作 RuleContainer
(如您所说)并发挥各种聪明才智来手动强制执行它,但您生活在现实世界中,我生活在现实世界中,而您只是 不需要为此需要容器对象,只需使用数组即可。
如果您的问题只是 enforcement
主题对象类型 a lá List<className>()
中的一个 enforcement
,您不能在 PHP[=25= 中执行此操作] 老实说,它在发现它的语言中的使用值得商榷(我知道我会因为这样说而投票,但我仍然是对的)//除了它有助于进一步阐明列表的目的//在老实说,我 20 多年的编程经验几乎涵盖了所有语言(机器代码 perl 和 fortran 除外),我可以告诉你这样的结构,根本不值得人力开销,它们可能包括间接的意外负担,超过它们的实际价值:
一个简单的妥协是:不偷懒,开始为数组命名而不是像 tmpList
这样的东西,如果你绝对确定实施一个简单的 test
到 http://php.net/manual/en/function.get-class.php 在 forloops 开始你肯定最终使用
我有一个名为 Rule 的 class,我将要创建一个 RuleContainer class,它实际上是 Rule 对象数组。
我想知道是否有创建新 class 的替代方法。有什么(现代)方法可以解决这个问题吗?也就是说,类似于使用 SPL 定义 一个只允许添加特定 class.
对象的数组如果不是,我应该在我的 RuleContainer 中实现哪个接口 class?
在你的情况下,我会实施 Iterator
interface in the RuleContainer
, as I've done several times when I needed a sort of Collection<T>
as we know it from other (typed) languages. And in the add(Rule $item)
or addItem(Rule $item)
method I'd make sure with the type definition of the argument (or using instanceof
) 要添加的项目的类型 Rule
。
最适合您任务的 class 是 SplObjectStorage
,但它不允许 class 类型提示。
我想,你可以这样做:
class RuleContainer extends SplObjectStorage
{
function attach(Rule $rule)
{
parent::attach($rule);
}
function detach(Rule $rule)
{
parent::detach($rule);
}
}
等等。您可以阅读 php.net
上的 SplObjectStorage
界面并决定您将使用什么以及需要覆盖什么。
根据容器的使用模式class,您需要实现以下接口中的一个或多个:
Iterator
- 将其用作foreach($container as $key => $value)
;Countable
- 对于count($container)
;ArrayAccess
- for$container[$key]
(设置它,得到它,检查它是否isset()
,unset()
它);
PHP 数组例程接口的使用
您可以实现您的目标,例如,ArrayAccess
implementation. Together with Iterator
它看起来像:
class ArrayStorage implements Iterator, ArrayAccess
{
private $holder = [];
private $instanceName;
public function __construct($instanceName)
{
if (!class_exists($instanceName)) {
throw new \Exception('Class '.$instanceName.' was not found');
}
$this->instanceName = $instanceName;
}
public function rewind()
{
reset($this->holder);
}
public function current()
{
return current($this->holder);
}
public function key()
{
return key($this->holder);
}
public function next()
{
next($this->holder);
}
public function valid()
{
return false !== $this->current();
}
public function offsetSet($offset, $value)
{
if (!($value instanceof $this->instanceName)) {
throw new \Exception('Storage allows only '.$this->instanceName.' instances');
}
if (is_null($offset)) {
$this->holder[] = $value;
} else {
$this->holder[$offset] = $value;
}
}
public function offsetExists($offset)
{
return isset($this->holder[$offset]);
}
public function offsetUnset($offset)
{
unset($this->holder[$offset]);
}
public function offsetGet($offset)
{
return isset($this->holder[$offset]) ? $this->holder[$offset] : null;
}
}
进程数
所以 - 是的,您正在明确地进行 instanceof
检查,但是 class 的最终用户并不知道这一点。只能在此存储的上下文中对有效实例进行操作(您可以查看 this fiddle 以获取使用示例)。概念是这样的:
$storage = new ArrayStorage('Foo'); //define what we will accept
$storage[] = new Foo; //fine, [] array-writing
$storage['baz'] = new Foo; //fine, key set
foreach ($storage as $key => $value) {
echo($key. ' => '.PHP_EOL.var_export($value, 1).PHP_EOL);
}
//invalid, will not pass. Either throw exception or just ignore:
$storage['bee'] = new Bar;
结束失败检查行为由您决定,但我认为,抛出异常是这里的最佳选择,因为它们是可捕获的,因此,最终用户可以决定在这种情况下要做什么。进一步的选择可能是将 Countable
添加到存储中,但它不会改变一般想法。
缺点
缺点 - 不,您将无法 "typehint" 它以某种方式。虽然它很有用,但在文档块中您仍然需要显示您接受哪种实体。在通用语言特性方面,Joe Watkins 提出了 arrayof RFC,它是为 PHP 5.6 版提出的,但不幸的是,它失败了。可能会在下一个版本中重新考虑。
您可以自己制作 RuleContainer
(如您所说)并发挥各种聪明才智来手动强制执行它,但您生活在现实世界中,我生活在现实世界中,而您只是 不需要为此需要容器对象,只需使用数组即可。
如果您的问题只是 enforcement
主题对象类型 a lá List<className>()
中的一个 enforcement
,您不能在 PHP[=25= 中执行此操作] 老实说,它在发现它的语言中的使用值得商榷(我知道我会因为这样说而投票,但我仍然是对的)//除了它有助于进一步阐明列表的目的//在老实说,我 20 多年的编程经验几乎涵盖了所有语言(机器代码 perl 和 fortran 除外),我可以告诉你这样的结构,根本不值得人力开销,它们可能包括间接的意外负担,超过它们的实际价值:
一个简单的妥协是:不偷懒,开始为数组命名而不是像 tmpList
这样的东西,如果你绝对确定实施一个简单的 test
到 http://php.net/manual/en/function.get-class.php 在 forloops 开始你肯定最终使用