对于重写的父方法,更严格的类型提示?

Consider the following to classes:

class objectCollection implements Iterator {

  private $objectArray = [];
  private $position = 0;


  public function __construct() {
      $this->position = 0;
  }

  public function add( $object ){
    if(!in_array( $object, $this->objectArray))
      $this->objectArray[] = $object;
    return $this;
  }

  public function remove( $object ){
    if(($key = array_search( $object, $this->objectArray())) !== false)
      unset($this->objectArray[$key]);
    return $this;
  }

  public function rewind() {
      $this->position = 0;
  }

  public function current() {
      return $this->objectArray[$this->position];
  }

  public function key() {
      return $this->position;
  }

  public function next() {
      ++$this->position;
  }

  public function valid() {
      return isset($this->objectArray[$this->position]);
  }

}

class attachmentCollection extends objectCollection {

  public function add( attachment $attachment ){
    return parent::add($attachment);
  }

  public function remove( attachment $attachment ){
    return parent::remove($attachment);
  }

}

This produces the follwing error: Declaration of attachmentCollection::add() should be compatible with objectCollection::add($object)

When you look at the code, I think it's rather obvious what I am trying to do. I want the attachmentCollection to essentially be the same as the objectCollection, except that the objects that can be added ( or removed ) need to be an instance of attachment.

What is the right way to do this ?

PHP errored code

PHP working code

Change this to

public function add( $object ){
    if(!in_array( $object, $this->objectArray))
      $this->objectArray[] = $object;
    return $this;
  }


public function remove( $object ){
    if(($key = array_search( $object, $this->objectArray())) !== false)
      unset($this->objectArray[$key]);
    return $this;
  }

This

public function add(attachment $object ){
    if(!in_array( $object, $this->objectArray))
      $this->objectArray[] = $object;
    return $this;
 }
public function remove(attachment $object ){
    if(($key = array_search( $object, $this->objectArray())) !== false)
      unset($this->objectArray[$key]);
    return $this;
  }

If nobody has a better solution, here is what I went with ( still open to a better solution ):

class attachmentCollection extends objectCollection {

  public function add( $attachment ){
    if(! $attachment instanceof attachment) throw new \Exception('Argument must be instance of attachment');
    return parent::add($attachment);
  }

  public function remove( $attachment ){
    if(! $attachment instanceof attachment) throw new \Exception('Argument must be instance of attachment');
    return parent::remove($attachment);
  }

}

in the case you want to extend further classes from the objectClass and the methods should be compatible, then i would recommend to use an Interface as the passed parameter, for example:

interface collection{     
   //your methods
}

class objectCollection implements Iterator {

    private $objectArray = [];
    private $position = 0;

    public function add(collection $object){
      if(!in_array( $object, $this->objectArray))                       
        $this->objectArray[] = $object;
        return $this;
    }

    public function remove(collection $object ){
       if(($key = array_search( $object, $this->objectArray())) !==false)
        unset($this->objectArray[$key]);
        return $this;
    }
  ....
}


 class attachmentCollection extends objectCollection {

    public function add(collection $attachment ){
       return parent::add($attachment);
    }

    public function remove( collection $attachment ){
       return parent::remove($attachment);
    }

 }

 class productCollection extends objectCollection {

     public function add(collection $attachment ){ 
        return parent::add($attachment);
     }

     public function remove(collection $attachment ){
         return parent::remove($attachment);
     }

 }


 class attachment  implements  collection {
    //implement interface methods
 }

class product implements collection{
   //implement interface methods 
 }