Search code examples
phpstrict

php strict error by including


It looks like strict errors do not occur if the classes are in one file like this:

abstract class Food{}

class Meat extends Food{}                    

abstract class Animal{          
    function feed(Food $food){ }
}

class Cat extends Animal{           
    function feed(Meat $meat){
        parent::feed($meat);
    }   
}    

But if you put the class definition in separate files and include them like that:

abstract class Food{}

class Meat extends Food{}                    

require 'Animal.php';
require 'Cat.php';

Strict standards error message is thrown:

Strict standards: Declaration of Cat::feed() should be compatible with Animal::feed(Food $food) in c:\path\to\Cat.php on line...

If all is in one file even this is ok:

class Dog extends Animal{           
  function feed($qty = 1){ 
    for($i = 0; $i < $qty; $i++){
        $Meat = new Meat();
        parent::feed($Meat);
    }       
  } 
}

Is this the intended behavior?

Because Meat is a Food, there shouldn't be a complain in the first place, right? So the solution is plain and clear: Put everything in one file and strict standards are satisfied ;)

Any hints appreciated


Solution

  • Is this the intended behavior?

    Unfortunately, yes. The intricacies that come into play with class declarations make it so that strict rules aren't always applied when they all occur in the same script; a single class per file doesn't exhibit this issue.

    Because Meat is a Food, there shouldn't be a complain in the first place, right?

    Wrong for two reasons:

    1. Meat is a smaller type than Food and therefore by only allowing the smaller type in your descendent class you're violating LSP; you can't substitute Cat for Animal.

    2. In PHP, argument types are invariant when overloading methods, i.e. the accepted types must match exactly that of the parent. While it could be argued that contravariant types make sense, due to technical reasons this can't be done.

    So the solution is plain and clear: Put everything in one file and strict standards are satisfied ;)

    No, and you should definitely not rely on that behaviour.