Can you override interface methods with different, but “compatible”, signatures?

后端 未结 7 1268
长发绾君心
长发绾君心 2021-02-07 01:32

Consider the following PHP interfaces:

interface Item {
    // some methods here
}

interface SuperItem extends Item {
    // some extra methods here, not define         


        
7条回答
  •  轮回少年
    2021-02-07 01:33

    PHP 7.4, released November 2014 has improved type variance.

    The code from the question remains invalid:

    interface Item {
        // some methods here
    }
    
    interface SuperItem extends Item {
        // some extra methods here, not defined in Item
    }
    
    interface Collection {
        public function add(Item $item);
        // more methods here
    }
    
    interface SuperCollection extends Collection {
        public function add(SuperItem $item); // This will still be a compile error
        // more methods here that "override" the Collection methods like "add()" does
    }
    

    Because the Collection interface guarantees that anything that implements it can accept any object of type Item as the parameter of add.

    However, the following code is valid in PHP 7.4:

    interface Item {
        // some methods here
    }
    
    interface SuperItem extends Item {
        // some extra methods here, not defined in Item
    }
    
    interface Collection {
        public function add(SuperItem $item);
        // more methods here
    }
    
    interface SuperCollection extends Collection {
        public function add(Item $item); // no problem
        // more methods here that "override" the Collection methods like "add()" does
    }
    

    In this case Collection guarantees that that it can accept any SuperItem. Since all SuperItems are Items, SuperCollection also makes this guarantee, while also guaranteeing that it can accept any other type of Item. This is known as a Contravariant method parameter type.

    There is a limited form of type variance in earlier versions of PHP. Assuming other interfaces are as in the question, the SuperCollection may be defined as:

    interface SuperCollection extends Collection {
        public function add($item); // no problem
        // more methods here that "override" the Collection methods like "add()" does
    }
    

    This can be interpreted as meaning any value whatsoever may be passed to the add method. That of course includes all Items, so this is still type safe, or it can be interpreted as meaning that an unspecified class of values, generally documented as mixed may be passed and the programmer needs to use other knowledge of exactly what can work with the function.

提交回复
热议问题