Reputation: 2071
I have confused from an example in php manual. It's about visibility. Here is the example.
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();
?>
http://www.php.net/manual/en/language.oop5.visibility.php
This example outputs
Bar::testPrivate
Foo::testPublic
Please can you explain how this happen?
why both testPublic()
are not called?
I put a var_dump($this)
in Bar class construct. It prints object(Foo)[1]
. The thing I know is private properties can be called withing same class.
Then how "Bar::testPrivate
" is called?
Upvotes: 6
Views: 184
Reputation: 173572
Then how "Bar::testPrivate" is called?
When you call $myFoo->test()
, it runs the code in the context of Bar
because the Foo
class didn't override it.
Inside Bar::test()
, when $this->testPrivate()
gets called, the interpreter will look at Foo
first but that method is private (and private methods from descendent classes can't be called from Bar
), so it goes one level up until it can find a suitable method; in this case that would be Bar::testPrivate()
.
In contrast, when $this->testPublic()
gets called, the interpreter immediately finds a suitable method in Foo
and runs it.
Edit
why both testPublic() are not called?
Only one method gets called when you run $this->testPublic()
, the furthest one (in terms of distance to the base class).
If Foo::testPublic()
needs to also execute the parent's implementation, you should write parent::testPublic()
inside that method.
Upvotes: 6
Reputation: 5679
I guess the comment of user 'omega at 2093 dot es' (http://www.php.net/manual/en/language.oop5.visibility.php#109324) is describing the same thing. There is said: "Methods defined in a parent class can NOT access private methods defined in a class which inherits from them. They can access protected, though."
In your case $this
object in Bar::test()
method is of Foo
type (your var_dump proves that). Because Foo::testPrivate()
method is private, it cannot be accessed from parent class Bar, and the only method, which can be accessed remains Bar::testPrivate()
(try to comment definition, and you'll get fatal error). That is why first output is Bar::testPrivate
.
The line $this->testPublic();
calls Foo::testPublic()
method, because $this
is of Foo
type and method is defined as public.
To be short, private methods are accessible only from the class, where they are defined. They cannot be accessed neither from child nor from parent classes.
To make the method accessible from child or parent classes make it protected. For example, if you'll make testPrivate()
method protected in both classes, it will print Foo::testPrivate Foo::testPublic
.
Upvotes: 1
Reputation: 9444
Private
doesn't mean you can't call it. It means that you can only call it from the current class. Public
means that you can call it from any class.
To call Bar::testPrivate
, try this:
$Bar->testPublic();
or
parent::testPublic();
BUT, you can't call $Bar->testPrivate()
because the method is private
.
Upvotes: 1
Reputation: 1099
The class Foo extends the class Bar. Then the function test is called wich is defined in Bar. In this function are two calls. One to the public and one to the private function in the class Bar.
Upvotes: 0
Reputation: 4489
You call
$myFoo->test();
See function test
:
public function test() {
$this->testPrivate();
$this->testPublic();
}
When this is called on an instance of a Bar
class (including inherited classes) it invokes testPrivate
and testPublic
.
These methods are overridden in class Foo
, that means the methods of Foo
are used. You can always call method of a base class:
// in Foo
public function testPublic() {
parent::testPublic();
echo "Foo::testPublic\n";
}
Bar::testPrivate
is called because it is private
and not overridden by Foo::testPrivate
.
Upvotes: 1
Reputation: 80639
Your function lies in the Bar
class and you are using the magic $this
pointer to call the member functions.
Try moving the function test()
to Foo
class, and see what happens. The output shall be:
Foo::testPrivate
Foo::testPublic
In your example, the private function of Bar was called because it was applicable only to that class. The class Foo does not have a test
function in it, and hence the test function from Bar
class has no access to call them.
Then, class Foo
's public function was called instead of Bar
's because of function overloading.
Both the classes have a function of that name, so the child class's function has importance.
Upvotes: 2