Nat*_*ing 5 php oop strong-typing
我正在研究一个框架,我试图尽可能强烈地输入.(我在PHP中工作并从C#中学习了一些我喜欢的想法并试图在这个框架中使用它们.)我正在创建一个Collection类,它是域实体/对象的集合.它有点模仿List<T>.Net中的对象.
我遇到了阻碍我输入这个课程的障碍.如果我有一个UserCollection,它应该只允许User对象进入它.如果我有一个PostCollection,它应该只允许Post对象.
此框架中的所有集合都需要具有某些基本功能,例如添加,删除,迭代.我创建了一个界面,但发现我无法执行以下操作:
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();
  }
 }
}
当我尝试运行此代码时,我得到syntax error, unexpected T_STRING, expecting T_VARIABLE or '$'了instanceof声明.对该问题进行了一些研究,看起来原因的根源在于$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变量.
使用静态也可以正常工作:
<?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());
实际上,您可能无论如何都想add()在类上定义您的方法Collection,这意味着您必须使用get_class()来解决一些奇怪的问题self::type,甚至self::$_type总是想返回基Collection类,所以这可能会起作用:
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());