php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71119 Cannot override methods on extended classes
Submitted: 2015-12-14 18:28 UTC Modified: 2015-12-15 14:32 UTC
From: chazmead89 at gmail dot com Assigned:
Status: Not a bug Package: *General Issues
PHP Version: 7.0.0 OS: Mac OSX 10.8.5
Private report: No CVE-ID: None
 [2015-12-14 18:28 UTC] chazmead89 at gmail dot com
Description:
------------
PHP Warning:  Declaration of B::foo(string $boo) should be compatible with A::foo(array $bar) in php shell code on line 3

This should not be a warning... this is basic method overriding, and should be perfectly good code.

For some reason I get a fatal error on apache handler, but only warning on CLI, possibly Xdebug RC4 escalating it as a bug in XDdebug.

Test script:
---------------
class A {
  public function foo(string $bar) { print_r($bar); }
}

class B extends A {
  public function foo(array $bar) { print_r($bar); }
}

Actual result:
--------------
PHP Warning:  Declaration of B::foo(string $boo) should be compatible with A::foo(array $bar) in php shell code on line 3

Warning: Declaration of B::foo(string $boo) should be compatible with A::foo(array $bar) in php shell code on line 3

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-12-14 19:35 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2015-12-14 19:35 UTC] requinix@php.net
"Basic method overriding" is you making sure your child class conforms to the interface specified by the parent class. That includes type hints.
 [2015-12-15 08:46 UTC] chazmead89 at gmail dot com
If the parent class specifies an interface without specifying an interface.. then what is the point in the Interface type?
 [2015-12-15 09:00 UTC] chazmead89 at gmail dot com
What about this test case then, called Method overloading..

class A {
  public function foo(array $bar) { print_r($bar); }
}

class B extends class A {
  public function foo(array $bar, string $baz) { print_r([$bar, $baz]); }
}

Is it now impossible to override / overload a class methods EVEN if there is no interface defined... if there was an interface defined I'd appreciate that any subclass needs to conform to that interface.. but otherwise the class is just a class and methods should be completely overridable and overloadable.  There are literally millions of cases where this may be required, and if you don't think its a bug, then I'll raise another ticket and try get someone else with a brain to look at this.
 [2015-12-15 14:00 UTC] nikic@php.net
FYI "override" and "overload" are not the same thing. What you say would make sense if this would create a method overload. However PHP does not support method overloading.
 [2015-12-15 14:04 UTC] inefedor at gmail dot com
I'm not sure why you're putting a slash between overriding and overloading, these two are completely different matters.

Overloading is a form of dynamic dispatch when the concrete method is found during runtime based on the instance type AND argument types. PHP doesn't have that meaning that.

Now overriding is when you override a method with another polymorphic method. They have to be compatible, otherwise due to the nature of PHP's method dispatch (when all methods are virtual) you'd have an error in otherwise type-safe cases like this:

class A { function foo(A $a) {} }
class B { function foo(B $a) {} }

$a = new B;

bar($a);

function bar(A $a) {
    $a->foo(new A);
}
 [2015-12-15 14:08 UTC] nospam at example dot org
"someone with brain" is 100% of php team and all of them will agree that 1- all dynamically typed languages don't have method overloading 2- it's pretty much impossible for them to have it 3- you should use java
 [2015-12-15 14:32 UTC] chazmead89 at gmail dot com
So here's my usecass.. I have a class, which is invokable, I use a dependancy injector to call the invoke method, the class defines a bunch of other methods which invoke uses to create a callable.

simplified:

class A {
  protected $_class = NULL;
  protected $_method = NULL;

  public function __construct(string $class, string $method) {
    $this->_class = $class;
    $this->_method = $method;
  }

  public function __invoke(Dependancy $dep) {
    $c = $this->getCallable();
    return $c($dep);
  }

  protected function getCallable(): callable {
    return [ new $this->_class, $this->_method ];
  }
}

Now I want to add extra dependancies to an extending class for additional functionality:

class B extends A {
  public function __invoke(Dependancy $dep, Additional $dep2) {
    // DO some additional stuff...
    if ( $dep2 === True ) {
      $c = [ $this, 'anotherCallableBecauseTrue' ];
      return $c($dep, $dep2);
    }
    return parent::__invoke($dep);
  }
}

This was never an issue in PHP5.. so I guess can you link me to the RFC discussion where this was changed?
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat May 04 22:01:33 2024 UTC