php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78841 Unable to override a private function when called from parent class
Submitted: 2019-11-20 07:05 UTC Modified: 2019-11-20 07:41 UTC
From: andrew at nicols dot co dot uk Assigned:
Status: Not a bug Package: Class/Object related
PHP Version: 7.4.0RC6 OS: Any
Private report: No CVE-ID: None
 [2019-11-20 07:05 UTC] andrew at nicols dot co dot uk
Description:
------------
If I have a class which defines a private function (innerClick), and a public function (click).
And I have the public function call the private function.
And I then extend the class.
It is possible to define a new implementation of the innerClick() function.

HOWEVER... it is not called by any function in the original class.
AND no error or warning is ever shown.

The following example attempts to demonstrate:

https://3v4l.org/XL6O1

The innerClick function is called from a click function.
I have extended the base class and instantiated that new class.
When I call the public function on the child class (which is actually in the base class), it calls the innerClick function on the base class.

This behaviour seems to have changed between PHP 5.1 and 5.2.

This behaviour makes sense when you consider that the original class is aware that the original functions were private, and therefore as per the strictest interpretation of visibility rules ("Private limits visibility only to the class that defines the item"), however it is extremely counter-intuitive.

I would argue that, as a minimum:
a) a warning should be shown to the user

In an ideal world I would argue that:
b) support of the current behaviour should be deprecated

In future I would argue that:
c) the behaviour flips and it becomes possible to call an overridden version of the private function in a child class

It looks like this behaviour has previously been raised in #37320 and was closed as not a bug. I would argue that this should be re-considered given many of the other recent changes and RFC that have been voted upon to improve the consistency of the language.

This is a confusing behaviour and should, at the very least, show a warning.

Test script:
---------------
<?php

class base
{
    public function click()
    {
        $this->innerClick();
    }

    private function innerClick()
    {
        echo "Called innerClick from base.\n";
    }
}

class extension extends base
{
    protected function innerClick()
    {
        echo "Called innerClick from extension.\n";
    }
}

$example = new extension();
$example->click();

Expected result:
----------------
Called innerClick from extension.

Actual result:
--------------
Called innerClick from base.


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-11-20 07:22 UTC] Wes dot example at example dot org
This is the expected behavior. Private methods don't get inherited therefore they can be called only from the methods defined in the very same class (base in your example). It doesn't matter whether you extend the class or not. The caller is still a method in "base".
 [2019-11-20 07:41 UTC] requinix@php.net
-Status: Open +Status: Not a bug -Type: Feature/Change Request +Type: Bug
 [2019-11-20 07:41 UTC] requinix@php.net
^
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 15:01:29 2024 UTC