【问题标题】:Stricter type hinting for overridden parent method?覆盖父方法的更严格的类型提示?
【发布时间】:2017-08-15 17:09:32
【问题描述】:

考虑以下类:

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

}

这会产生以下错误: attachmentCollection::add() 的声明应该与 objectCollection::add($object) 兼容

当您查看代码时,我认为我正在尝试做的事情相当明显。 我希望attachmentCollectionobjectCollection 基本相同,只是可以添加(或删除)的对象必须是attachment 的实例。

这样做的正确方法是什么?

【问题讨论】:

  • 据我所知,php 不支持重载的方式与高级语言所支持的方式相同...那些必须具有相同的签名...
  • 哦,好的。真可惜。

标签: php inheritance type-hinting


【解决方案1】:

PHP errored code

PHP working code

把这个改成

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 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;
  }

【讨论】:

  • 感谢您的回答!当然,这消除了错误,但我不能使用不同的类型提示从 objectCollection 扩展其他类。例如,像“productCollection”,“add”方法只接受“product”对象
  • @minychillo 如果您使用的是strict_types,那么您也必须在父类中遵循它。
【解决方案2】:

如果没有人有更好的解决方案,这就是我的想法(仍然对更好的解决方案持开放态度):

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

}

【讨论】:

    【解决方案3】:

    如果您想从 objectClass 扩展更多类并且方法应该兼容,那么我建议使用接口作为传递的参数,例如:

    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 
     }
    

    【讨论】:

      猜你喜欢
      • 2014-04-18
      • 2011-04-17
      • 2021-11-16
      • 2017-11-18
      • 2017-12-19
      • 1970-01-01
      • 1970-01-01
      • 2020-11-30
      相关资源
      最近更新 更多