PHP 'instanceof' failing with class constant

只愿长相守 提交于 2019-12-05 10:18:26

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());

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());

Another workaround is to do:

$type = self::type;
if (!($obj instanceof $type))

Just 'cause it's a constant doesn't mean you can't put it in a variable for a moment to satisfy the parser.

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.

It's generally not a good idea to write one language in another language. You don't need Collections in PHP.

If you're going continue down that road, perhaps you should consider using tools supplied to you by PHP. For example, there's ArrayObject, which you can inherit from and override the required methods to ensure that only properly typed things enter the array. ArrayObjects can be used anywhere in PHP where a normal array can be used. Also, the underlying bits and pieces have already been written for you.

The rest of the Standard PHP Library may be of some interest to you, the SplObjectStorage class in particular.

I'm surprised by this behavior as well, but this should work:

$type = self::type;
if(!($obj instanceof $type)) {
    throw new UhOhException();
}

EDIT:

You could do

abstract class Collection {
    const type = null;
    protected $type = self::type;
}
class PostCollection extends Collection {
    const type = "User";
    public function add($obj) {
        if(!($obj instanceof $this->type)) {
            throw new WhateverException();
        }
    }
}

But you're turning on the complicometer. This has the additional overhead of creating an instance $type variable for each instance of PostCollection (and no, you cannot just add static to the $type property).

it should readly be like this

public function add(ICollection $obj){

}

now if you try to add an object to the function add that is not an instance of Icollection(thats an example) then it will fail, before you even get to check using the instanceof.

Try using PHP's is_a function instead of instanceof as that expects a string as the Class name.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!