I didn't get why the first output of the code prints "Bar::testPrivate" as we are calling the test method of the parent class using sub class's instance.So, when calling the first line of code inside the test function which is "$this->testPrivate();" should call testPrivate method of the sub class hence printing "Foo::testPrivate" and not "Bar::testPrivate".
<pre>
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(); // Bar::testPrivate
// Foo::testPublic
</pre>
Your class Foo doesn't have a test() method. You can call $myFoo->test() because the method test() is inherited from class Bar. You'll have to override the method test() within class Foo just as you did with methods testPrivate() and testPublic().
You are correct that it is calling the method of the base class, but in this case Bar is your base class. Check out the example here.
If you are looking to inherit all the functions from your base (parent) class then you should explicitly call it's constructor in the child class. Otherwise you will need to override those methods. Also, when using the actual instance (i.e. you created an object) functions declared private are only available to that class. Use protected for classes that will inherit that function. e.g.:
class Foo {
public function __construct() {
echo "Foo constructed...\n";
$this->fooOnly();
}
private function fooOnly() {
echo "Called 'fooOnly()'\n"; //Only available to class Foo
}
protected function useThisFoo() {
echo "Called 'useThisFoo()'\n"; //Available to Foo and anything that extends it.
}
}
class Bar extends Foo {
public function __construct() {
parent::__construct(); //Now Bar has everything from Foo
}
public function testFooBar() {
//$this->fooOnly(); //Fail - private function
$this->useThisFoo(); //Will work - protected function is available to Foo and Bar
}
}
$bar = new Bar();
$bar->testFooBar(); //Works - public function will internally call protected function.
//$bar->fooOnly(); //Fail - private function can't be accessed in global space
//$bar->useThisFoo(); //Fail again - protected function can't be access in global space
Related
I am new to php and I was going through the documentation for the visibility. I am little confused with this example in the documentation.
when the call to $myFoo->test() is made, shouldn't it make a call to Foos $this->testPrivate(); . I mean shouldn't $this be Foos Object rather than Bar object? . As per my knowledge(I might be wrong here) Foo will have kind of its own test() method which is inherited from Bar and calling $myFoo->test() will make a call to '$this->testPrivate' where the $this should be Foos object myFoo. so How is it calling Bar's testPrivate method?
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(); // Bar::testPrivate
// Foo::testPublic
?>
test() is in Bar, and will call the highest-level methods that Bar has access to. It has access to Foo's testPublic (because it is public) so it can call that, but it doesn't have access to Foo's testPrivate() (because it's private to Foo) so it calls it's own testPrivate() instead
in php, is there any way to directly access any Base Class Property directly Via an object of a derived Class type.
For eg:
class a
{
public $name="Something";
function show()
{
echo $this->name;
}
};
class b extends a
{
public $name="Something Else";
function show()
{
echo $this->name;
}
};
$obj = new b();
$obj->show();
it'll Print string "Something Else", but what if i wish to access Base class Function show,
it doesn't seem to work like it is done in c++
obj.a::show();
Since you override $name in the child, the property will have the child's property value. You cannot access the parent value then. It wouldn't make sense any other way because the property is public, which means the property is visible to the child (and outside) and modifications to it will change the very base value. So it's effectively one and the same property and value for that instance.
The only way to have two separate properties of the same name is to declare the base property private and the child property non-private and then call a method that has access to the base property, e.g.
class Foo
{
private $name = 'foo';
public function show()
{
echo $this->name;
}
}
class Bar extends Foo
{
public $name = 'bar';
public function show()
{
parent::show();
echo $this->name;
}
}
(new Bar)->show(); // prints foobar
Since your C++ example call is using the scope resolution operator :: you might be looking for class/static properties:
class Foo
{
static public $name = 'foo';
public function show()
{
echo static::$name; // late static binding
echo self::$name; // static binding
}
}
class Bar extends Foo
{
static public $name = 'bar';
public function show()
{
parent::show(); // calling parent's show()
echo parent::$name; // calling parent's $foo
}
}
(new Bar)->show(); // prints barfoofoo
While coding and using late static binding in PHP I found some strange behaviour. A child object created with static() in its parent class can access the private methods of its parent.
Here's an example:
class Attachment
{
public static function createFromFile($file)
{
$attachment = new static();
echo get_class($attachment) . PHP_EOL;
$attachment->loadFromFile($file);
}
private function loadFromFile($file)
{
echo 'attachment';
}
}
class PictureAttachment extends Attachment
{
//...
}
PictureAttachment::createFromFile('example.txt');
Output:
PictureAttachment
attachment
Is this a correct behaviour?
Yes, this is correct. The class that is calling the private method is the same that is declaring it. It doesn't matter that it may or may not instantiate a child class. You just can't have any code in the child class calling the private method of the parent.
In other words:
class Foo {
protected function bar() {
$this->baz();
}
private function baz() { }
}
class Bar extends Foo {
protected function bar() {
parent::bar(); // <-- works
parent::baz(); // <-- doesn't work
}
}
How can I prevent the something method below to be created in the foo class ?
class fooBase{
public function something(){
}
}
class foo extends fooBase{
public function __construct(){
echo $this->something(); // <- should be the parent class method
}
public function something(){
// this method should not be allowed to be created
}
}
Use the final keyword (like in Java etc):
class fooBase{
final public function something(){
}
}
class foo extends fooBase{
public function __construct(){
echo $this->something(); // <- should be the parent class method
}
public function something(){
// this method should not be allowed to be created
}
}
See PHP Final keyword. Note that foo will still have a method something, but something will only come from fooBase and foo can't override it.
Use the final keyword.
In your parent:
final public function something()
You can use final to prevent base methods being overwritten.
class fooBase{
final public function something(){
}
}
Check below given code. I could not get that how it had called testPrivate() method of Class Bar class. As per my assumption it should call method from Foo class i.e. Foo::testPrivate.
Check the demo here
<?php
class Bar
{
public function test() {
$this->testPrivate();
$this->testPublic();
}
public function testPublic() {
echo "Bar::testPublic\n";
}
private function testPrivate() {
echo "<br>Bar::testPrivate\n";
}
}
class Foo extends Bar
{
public function testPublic() {
echo "<br>Foo::testPublic\n";
}
private function testPrivate() {
echo "<br>Foo::testPrivate\n";
}
}
$myFoo = new foo();
$myFoo->test(); // Bar::testPrivate
// Foo::testPublic
?>
If you want a child class to be able to overload a method defined in a parent class, that method has to be declared as protected -- and not as private.
Here, if you change your testPrivate methods definitions to :
protected function testPrivate() {
echo "<br>Bar::testPrivate\n";
}
and :
protected function testPrivate() {
echo "<br>Foo::testPrivate\n";
}
You'll get the output you expected :
Foo::testPrivate
Foo::testPublic
For more informations, you should take a look at the Visibility section of the manual -- quoting the first sentences :
Class members declared public can be
accessed everywhere. Members
declared protected can be accessed
only within the class itself and by
inherited and parent classes.
Members declared as private may
only be accessed by the class that
defines the member.
I think you misunderstand what a private method is. Foo::testPrivate() can only be call from inside Foo itself. You can acheive the behaviour you describe with a protected method. Protected means visible to the class and any classes which extend it.