"Overloading" a private method in PHP
oop, overloading, php
Solution
To fix the Notice, simply change `foo()` in the Child to
public function foo($arg = null) {
As to the question "why does this not work":
Visibility in PHP is strictly about runtime access. It doesn't affect how you can extend/compose/overload classes and methods. Loosening the visibility of a private method from a Supertype in a Subtype will add a separate method in the subtype with no access to the same named method in the supertype. However, PHP will assume a parent-child relationship for these. That didn't cause the Notice though. At least, not on it's own.
The reason why you get the Notice, is that you are then also trying to change the method signature. Your `foo()` does no longer require `$arg` to be passed to it. When you assume a parent-child relationship between the methods, this is a problem because the Liskov Substitution Principle states that "if S is a subtype of T, then objects of type T may be replaced with objects of type S" without breaking the program. In other words: if you have code that uses `Base`, you should be able to replace `Base` with `Child` and the program should still work as if it was using `Base`.
Assume your `Base` also has a public method `bar()`.
class SomeClientUsingBase
{
public function doSomethingWithBase(Base $base)
{
$result = $base->bar();
// …
Now imagine `Child` changes `bar()` to require an argument. If you then pass `Child` for `Base` into the client, you will break the client, because the client calls `$base->bar();` without an argument.
Obviously, you could change the client to pass an argument, but then the code really depends on how `Child` defined the method, so the Typehint is wrong. In fact, `Child` is not a `Base` then, because it doesn't behave like a `Base`. It's broken inheritance then.
Now the funny thing is, if you remove that `$arg` from `foo()`, you are technically not violating LSP, because the client would still work. The Notice is wrong here. Calling `$base->foo(42)` in a client that previously used `Base` will still work with a `Child` because the `Child` can simply ignore the argument. But PHP wants you to make the argument optional then.
Note that LSP also applies to what a method may return. PHP just doesn't include the return type in the signature, so you have take that into account yourself. Your methods have to return what the Supertype returned or something that is behaviorally equivalent.
Problem
I know I cannot overload methods in PHP. And, as far as I know, `private` methods in a class are invisible to classes that extend the base class. So why this does not work? ``` class Base { private function foo($arg) { print "Base $arg"; } } class Child extends Base { public function foo() { print "Child"; } } $c = new Child; print $c->foo(); ``` The error: `PHP Strict Standards: Declaration of Child::foo() should be compatible with Base::foo($arg) in /var/www/boludo.php on line 17` I assumed that `foo($arg)` method is invisible in `Child` class because is `private`. So, I'm not overloading `foo`, I'm just creating a method called `foo`.