title: PHP 'instanceof' failing with class constant
body: <p>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 <code>List&lt;T&gt;</code> object in .Net.</p>
  
  <p>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.</p>
  
  <p>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:</p>
  
  <pre><code>interface ICollection { public function add($obj) }
  class PostCollection implements ICollection { public function add(Post $obj) {} }
  </code></pre>
  
  <p>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:</p>
  
  <pre><code>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();
    }
   }
  }
  </code></pre>
  
  <p>When I attempt to run this code, I get <code>syntax error, unexpected T_STRING, expecting T_VARIABLE or '$'</code> on the <code>instanceof</code> statement.  A little research into the issue and it looks like the root of the cause is that <code>$obj instanceof self</code> is valid to test against the class.  It appears that PHP doesn't process the entire <code>self::type</code> constant statement in the expression.  Adding parentheses around the <code>self::type</code> variable threw an error regarding an unexpected '('.</p>
  
  <p>An obvious workaround is to not make the <code>type</code> variable a constant.  The expression <code>$obj instanceof $this-&gt;type</code> works just fine (if <code>$type</code> is declared as a variable, of course).</p>
  
  <p>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 <code>self::this</code> so that PHP won't die when processing it?</p>
  
  <p><strong>UPDATE</strong> 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?</p>
  
  <pre><code>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-&gt;type)) {
     throw new UhOhException();
    }
   }
  }
  </code></pre>
  
  <p><strong>UPDATE #2:</strong> 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 <code>protected</code> variable, I think.</p>