Bug #76370 [Opn->Nab]: Fatal error instead of warning when extending class that implements interface

From: Date: Sun, 05 Aug 2018 09:13:05 +0000
Subject: Bug #76370 [Opn->Nab]: Fatal error instead of warning when extending class that implements interface
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-216606@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=76370&edit=1

 ID:                 76370
 Updated by:         requinix@php.net
 Reported by:        kinglozzer at gmail dot com
 Summary:            Fatal error instead of warning when extending class
                     that implements interface
-Status:             Open
+Status:             Not a bug
 Type:               Bug
 Package:            Class/Object related
 Operating System:   Mac OS X
 PHP Version:        7.2.5
 Block user comment: N
 Private report:     N

 New Comment:

Not a bug.

It is not compatible because the parent implementation supports an argument while the child does
not.

https://en.wikipedia.org/wiki/Liskov_substitution_principle
LSP says that method arguments must be contravariant, meaning that a child method must accept at
least as much as its parent did. If the parent supports having an argument then the child must also
support having an argument. That argument can be made optional in the child, but it must still be
there.


> The introduction of an interface to the base class should not affect the behaviour of child
> classes.
I agree, but life isn't that simple: where the method was defined does matter. Dropping
parameters used to be allowed in PHP 4's lackluster implementation of OOP, so during PHP
5's overhaul it became an E_STRICT-able offense and later an E_WARNING. It remains a warning
for backwards compatibility. It shouldn't be allowed at all, though, so when defined in a
interface (introduced in PHP 5) it was immediately considered a fatal error.


Previous Comments:
------------------------------------------------------------------------
[2018-08-05 08:18:03] Wes dot example at example dot org

(assuming mixed includes all types including null)

class Foo {
    public function method(?X $arg = null) {}
}

class Bar extends Foo {
    public function method(){}
    // PHP should interpret this the same as
    // public function method(mixed $arg = null){}
}

class Baz extends Bar {
    // ...in order to disallow stuff like this:
    public function method(?Y $arg = null) {}
    // Error: parameter 1 must be mixed and be optional as in class Bar
}

------------------------------------------------------------------------
[2018-08-05 07:58:31] Wes dot example at example dot org

Not only it shouldn't be a fatal error, but shouldn't be a warning either. Parameters are
optional and untyped in all the signatures, hence going to one to the other should never cause
errors. That is because php does not reject trailing parameters.

function bar(mixed $one = null, mixed ...$foo){}
function bar(mixed $one = null, mixed $two = null){}
function bar(mixed ...$foo){}
function bar(){}

these are all compatible... because no parameter is ever required, in all of them

------------------------------------------------------------------------
[2018-05-24 08:37:31] kinglozzer at gmail dot com

Description:
------------
If a class implements an interface, any child classes method definitions must match the *parent
class* exactly (not the interface) or a fatal error will occur.

Unexpected behaviour - fatal error: https://3v4l.org/BeFp5

Expected behaviour - warning: https://3v4l.org/ZhHrE (without
implementing an interface).

The introduction of an interface to the base class should not affect the behaviour of child classes.

Test script:
---------------
https://3v4l.org/BeFp5

Expected result:
----------------
Warning: Declaration of Bar::method() should be compatible with Foo::method($arg = NULL)

Actual result:
--------------
Fatal error: Declaration of Bar::method() must be compatible with Foo::method($arg = NULL)


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=76370&edit=1


Thread (7 messages)

« previous php.bugs (#216606) next »