【发布时间】:2011-03-01 11:07:17
【问题描述】:
我正在开发一个框架,我正在尝试尽可能强地键入。 (我在 PHP 中工作,并从 C# 中获取我喜欢的一些想法,并尝试在这个框架中利用它们。)我正在创建一个 Collection 类,它是域实体/对象的集合。它有点模仿 .Net 中的 List<T> 对象。
我遇到了阻碍我输入这门课程的障碍。如果我有一个 UserCollection,它应该只允许用户对象进入它。如果我有 PostCollection,它应该只允许 Post 对象。
这个框架中的所有Collection都需要具备一定的基本功能,比如add、remove、iterate。我创建了一个界面,却发现无法做到以下几点:
interface ICollection { public function add($obj) }
class PostCollection implements ICollection { public function add(Post $obj) {} }
这破坏了它对界面的遵守。但是我不能强类型化接口,因为所有集合都是同一类型。所以我尝试了以下方法:
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 变量周围添加括号会引发有关意外 '(' 的错误。
一个明显的解决方法是不要将type 变量设为常量。表达式 $obj instanceof $this->type 可以正常工作(当然,如果 $type 被声明为变量)。
我希望有一种方法可以避免这种情况,因为我想将值定义为常量以避免以后对变量进行任何可能的更改。关于如何实现这一点的任何想法,或者在这方面我是否将 PHP 发挥到了极限?有没有办法“转义”或者封装self::this,让PHP在处理的时候不会死机?
更新根据下面的反馈,我想到了一些尝试——下面的代码有效!谁能想到 1) 不这样做的理由,2) 最终无法奏效的原因,或 3) 更好的方法来实现这一目标?
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 变量。
【问题讨论】:
-
我想我回答了 1 或 2 -- 即使变量是
protected,它仍然可以在代码中更改。这样做并没有真正的安全性,因为变量$type不会被意外更改。我所希望的就是为此提供保险。 -
如果我理解正确,您给 instanceof 操作提供了一个字符串 ($this->type),而它应该只是一个类名(参见 php.net/manual/en/language.operators.type.php)。我认为你应该改用'is_a',因为它需要一个字符串,这就是 $this->type 是什么。
-
不是一个真实的陈述 - 查看您链接到的页面上的示例 #5。
-
啊,真的,我的错,谢谢你的评论。
-
顺便说一下,2-空格缩进是异端。
标签: php oop strong-typing