Table of Contents

PHP RFC: Allow abstract function override

Proposal

PHP 7 introduced type declarations for return and improved ones for parameters. They currently support a very limited kind of variance (only to no-type):

<?php
class A           { function bar(stdClass $x){}  }
class B extends A { function bar($x): stdClass{} }

However, this isn't currently matched by the equivalent abstract declarations:

<?php
abstract class A           { abstract function bar(stdClass $x);  }
abstract class B extends A { abstract function bar($x): stdClass; }
class C extends B          { function bar($x): stdClass{} }
// Fatal error: Can't inherit abstract function A::bar()
// (previously declared abstract in B)

This RFC proposes to allow this, even if it has very few uses, and because there is no reason to disallow a compatible redefinition.

Additionally, it comes in handy for documentation:

interface A{
    function doSomething();
}
 
interface B extends A{
    function doSomethingElse();
}
 
abstract class AProxy implements A{
    abstract protected function getOrigin(): A;
    function doSomething(){
        return $this->getOrigin()->doSomething();
    }
}
 
// This phpdoc syntax has quirks in phpdocumentor
// apigen and phpstorm, and it's almost unmanageable
// as phpdoc interpreters have poor multiline support
// (imagine documenting all the parameters, the return
// type, all the throws...):
/** @method B getOrigin() */
abstract class BProxy extends AProxy implements B{
    /** @return B */ // This is much better!
    abstract protected function getOrigin(): A;
    function doSomethingElse(){
        return $this->getOrigin()->doSomethingElse();
    }
}

And, obviously, it will gain more uses when PHP will support a full-featured type variance.

Backward Incompatible Changes

None.

Proposed PHP Version(s)

7.2

Voting

2/3 majority required.

Accept abstract function override?
Real name Yes No
ashnazg (ashnazg)  
bwoebi (bwoebi)  
cyberline (cyberline)  
daverandom (daverandom)  
dm (dm)  
emir (emir)  
galvao (galvao)  
kelunik (kelunik)  
kguest (kguest)  
marcio (marcio)  
mariano (mariano)  
ocramius (ocramius)  
patrickallaert (patrickallaert)  
salathe (salathe)  
sammyk (sammyk)  
stas (stas)  
subjective (subjective)  
treffynnon (treffynnon)  
trowski (trowski)  
Final result: 16 3
This poll has been closed.

Patches and Tests

Pull request to handle the change: https://github.com/php/php-src/pull/2531

References

Discussion on externals.io