PHP'instanceof'失败,类常量 [英] PHP 'instanceof' failing with class constant

查看:124
本文介绍了PHP'instanceof'失败,类常量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力尝试尽可能强地键入的框架. (我正在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆