PHP'instanceof'失败,类常量 [英] PHP 'instanceof' failing with class constant
问题描述
我正在努力尝试尽可能强地键入的框架. (我正在PHP中工作,并从C#中提取了一些我喜欢的想法,并试图在此框架内利用它们.)我正在创建一个Collection类,该类是域实体/对象的集合.有点模仿.Net中的List<T>
对象.
I'm working on a framework that I'm trying to type as strongly as I possibly can. (I'm working within PHP and taking some of the ideas that I like from C# and trying to utilize them within this framework.) I'm creating a Collection class that is a collection of domain entities/objects. It's kinda modeled after the List<T>
object in .Net.
我遇到了阻碍我输入此类的障碍.如果我有一个UserCollection,它应该只允许User对象进入其中.如果我有PostCollection,则应该只允许Post对象.
I've run into an obstacle that is preventing me from typing this class. If I have a UserCollection, it should only allow User objects into it. If I have a PostCollection, it should only allow Post objects.
此框架中的所有Collections必须具有某些基本功能,例如add,remove和iterate.我创建了一个界面,但发现无法执行以下操作:
All Collections in this framework need to have certain basic functions, such as add, remove, iterate. I created an interface, but found that I couldn't do the following:
interface ICollection { public function add($obj) }
class PostCollection implements ICollection { public function add(Post $obj) {} }
这破坏了它对界面的遵从性.但是我不能对接口进行强类型化,因为这样所有Collection都属于同一类型.因此,我尝试了以下操作:
This broke it's compliance with the interface. But I can't have the interface strongly typed because then all Collections are of the same type. So I attempted the following:
interface ICollection { public function add($obj) }
abstract class Collection implements ICollection { const type = 'null'; }
class PostCollection extends Collection {
const type = 'Post';
public function add($obj) {
if(!($obj instanceof self::type)) {
throw new UhOhException();
}
}
}
当我尝试运行此代码时,在instanceof
语句上得到syntax error, unexpected T_STRING, expecting T_VARIABLE or '$'
.对问题进行一些研究,发现原因可能是$obj instanceof self
对类进行测试是有效的.看来PHP不会在表达式中处理整个self::type
常量语句.在self::type
变量周围加上括号会引发有关意外的'(')的错误.
When I attempt to run this code, I get syntax error, unexpected T_STRING, expecting T_VARIABLE or '$'
on the instanceof
statement. A little research into the issue and it looks like the root of the cause is that $obj instanceof self
is valid to test against the class. It appears that PHP doesn't process the entire self::type
constant statement in the expression. Adding parentheses around the self::type
variable threw an error regarding an unexpected '('.
一个明显的解决方法是不使type
变量为常数.表达式$obj instanceof $this->type
可以正常工作(当然,如果将$type
声明为变量).
An obvious workaround is to not make the type
variable a constant. The expression $obj instanceof $this->type
works just fine (if $type
is declared as a variable, of course).
我希望有一种避免这种情况的方法,因为我想将值定义为一个常量,以避免以后对该变量进行任何可能的更改.关于如何实现此目标的任何想法,或者在这方面我是否将PHP限制在极限范围内?有没有一种转义"或封装self::this
的方法,以使PHP在处理时不会死?
I'm hoping that there's a way to avoid that, as I'd like to define the value as a constant to avoid any possible change in the variable later. Any thoughts on how I can achieve this, or have I take PHP to it's limit in this regard? Is there a way of "escaping" or encapsulating self::this
so that PHP won't die when processing it?
更新根据以下反馈,我想到了一些可以尝试的方法-以下代码可以正常工作!谁能想到1)不这样做的原因,2)最终无法工作的原因或3)更好地实现这一目标的方法?
UPDATE Based on the feedback below, I thought of something to try -- the code below works! Can anyone think of 1) a reason not to do this, 2) a reason this won't ultimately work, or 3) a better way to pull this off?
interface ICollection { public function add($obj) }
abstract class Collection { const type = null; protected $type = self::type; }
class PostCollection extends Collection {
const type = 'Post';
public function add($obj) {
if(!($obj instanceof $this->type)) {
throw new UhOhException();
}
}
}
更新#2:将上面的代码投入生产后,事实证明它不起作用.我不知道在测试时它如何工作,但它根本不工作.我认为我只能使用protected
变量.
UPDATE #2: After putting the code above into production, it turns out it doesn't work. I have no idea how it worked when I tested it, but it doesn't work at all. I'm stuck with using a protected
variable, I think.
推荐答案
使用静态方法也可以正常工作:
This also works correctly, using a static:
<?php
interface ICollection {
public function add($obj);
}
abstract class Collection implements ICollection {
static protected $_type = 'null';
}
class PostCollection extends Collection {
static protected $_type = 'Post';
public function add($obj) {
if(!($obj instanceof self::$_type)) {
throw new UhOhException();
}
}
}
class Post {}
$coll = new PostCollection();
$coll->add(new Post());
实际上,您可能还是想在Collection
类上定义add()
方法,这意味着您必须使用get_class()
来解决与self::type
或什至总是与self::$_type
有关的某些怪异之处仍然想返回基Collection
类,所以这可能可行:
And actually, you probably want to define your add()
method on the Collection
class anyway, which means you'll have to use get_class()
to get around some weirdness with self::type
or even self::$_type
always wanting to return the base Collection
class anyway, so this would probably work:
abstract class Collection implements ICollection {
const type = 'null';
public function add($obj) {
$c = get_class($this);
$type = $c::type;
if(!($obj instanceof $type)) {
throw new UhOhException();
}
}
}
class PostCollection extends Collection {
const type = 'Post';
}
class Post {}
$coll = new PostCollection();
$coll->add(new Post());
这篇关于PHP'instanceof'失败,类常量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!