Faery
Faery

Reputation: 4650

Inheritance and visibility - PHP

I have difficulties in understanding why we get the output of this code:

<?php

class Bar 
{
    public function test() {
        $this->testPrivate();
        $this->testPublic();
    }

    public function testPublic() {
        echo "Bar::testPublic\n";
    }

    private function testPrivate() {
        echo "Bar::testPrivate\n";
    }
}

class Foo extends Bar 
{
    public function testPublic() {
        echo "Foo::testPublic\n";
    }

    private function testPrivate() {
        echo "Foo::testPrivate\n";
    }
}

$myFoo = new foo();
$myFoo->test(); 
?>

So Foo extends Bar. $myfoo is an obect of the class Foo. Foo doesn't have a method, called test(), so it extends it from its parent Bar. But why the result of test() is

Bar::testPrivate 
Foo::testPublic

Can you please explain me why the first isn't Foo::testPrivate, when this parent's method is overridden in the child?

Thank you very much in advance!

Upvotes: 20

Views: 1265

Answers (6)

Wolfgang Fahl
Wolfgang Fahl

Reputation: 15614

This is not PHP specific. Inheritance rules call for protected and public functions to be overridable. Private functions have their own scope and are invisible for the generalized class.

Please find below the same situation in Java, same result:

Bar::testPrivate

Foo::testPublic

Except you might get a warning

The method testPrivate() from the type Foo is never used locally    Foo.java    

since Java is compiled.

public class Bar 
{
    public void test() {
        this.testPrivate();
        this.testPublic();
    }

    public void testPublic() {
        System.out.println("Bar::testPublic\n)");
    }

    private void testPrivate() {
        System.out.println( "Bar::testPrivate\n");
    }
}

public class Foo extends Bar {
    public void testPublic() {
        System.out.println("Foo::testPublic\n");
    }

    private void testPrivate() {
        System.out.println("Foo::testPrivate\n");
    }

    public static void main(String[] args) {
        Foo myFoo = new Foo();
        myFoo.test();
    }
}

Upvotes: 3

F.P
F.P

Reputation: 17831

Because private means private. No other class, not even child-classes know about Bar::testPrivate() and therefore cannot override something they don't even know about.

You can use Foo::testPrivate() only inside Foo. Because that's what private is all about.

More information: Strange behavior when overriding private methods

Upvotes: 5

Louis Huppenbauer
Louis Huppenbauer

Reputation: 3714

Probably becuase testPrivate is, as the name already suggests, a private method and won't be inherited / overwritten by class inheritance.

On the php.net manual page you probably got that code from it explicitely states that We can redeclare the public and protected method, but not private

So, what exactly happens is the following: The child class will not redeclare the method testPrivate but instead creates it's own version in the "scope" if the child object only. As test() is defined in the parent class, it will access the parents testPrivate.

If you would redeclare the test function in the child class, it should access the childs? testPrivate() method.

Upvotes: 12

PatrikAkerstrand
PatrikAkerstrand

Reputation: 45731

Private methods are not visible to anything but the declaring class. Since you call testPrivate from the parent class, the only method it has access to is its own declaration of the method. Thus you get the output you see. Had the access modifier been protected, however, then you would get the output you expect, since protected methods are visible throughout the inheritance chain.

Upvotes: 6

laurent
laurent

Reputation: 90863

private members cannot be overridden, only public and protected ones can. It means that, in fact, testPrivate is not overridden, so Bar cannot see it and still calls its own testPrivate.

Upvotes: 5

JvdBerg
JvdBerg

Reputation: 21866

From the manual:

Members declared as private may only be accessed by the class that defines the member.

As your test function runs in the base class Bar, it will access the private function in its own class.

Upvotes: 3

Related Questions