Visibility in PHP? context of `$this` when inherited? - php

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

Related

PHP Object Oriented Programming Oops Issues

I am trying to implement a code somewhat like below but not able to understand one issue, as per my understanding it should have printed the data like this:
Foo::testPrivate
Foo::testPublic
But its displaying output as ::
Bar::testPrivate
Foo::testPublic
The code is::
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();
Can somebody please explain this?
As per my Understanding
Displaying output is right because of you are created object of "Foo" class and then after call test() function is inside the "Bar" class
In test() function of Bar class is call testPrivate() using "this" keyword so call the function in same class and testPrivate() is also private so that's why display result like :
Bar::testPrivate
Foo::testPublic
Make changes to private function testPrivate() { } to public function testPrivate() in both the class for displayed your accepted result
Result after made this changes is :
Foo::testPrivate
Foo::testPublic

How to call non-static method from static method of same class?

I am working on PHP code.
Here is the sample code to explain my problem:
class Foo {
public function fun1() {
echo 'non-static';
}
public static function fun2() {
echo "static" ;
//self::fun1();
//Foo::fun1();
}
}
How can I call the non-static method from the static method ?
Note: Both functions are used throughout the site, which is not known. I
can't make any changes in the static/non-static nature of them.
You must create a new object inside the static method to access non-static methods inside that class:
class Foo {
public function fun1()
{
return 'non-static';
}
public static function fun2()
{
return (new self)->fun1();
}
}
echo Foo::fun2();
The result would be non-static
Later edit: As seen an interest in passing variables to the constructor I will post an updated version of the class:
class Foo {
private $foo;
private $bar;
public function __construct($foo, $bar)
{
$this->foo = $foo;
$this->bar = $bar;
}
public function fun1()
{
return $this->foo . ' - ' . $this->bar;
}
public static function fun2($foo, $bar)
{
return (new self($foo, $bar))->fun1();
}
}
echo Foo::fun2('foo', 'bar');
The result would be foo - bar
The main difference would be that you can call static methods for a class without having to instantiate an object of that class.
So, in your static method try
Foo $objInst = new Foo();
$objInst->fun1();
But I don't see how this would make any sense in any context.

why php allow to overwriting private method?

In the documentation is this example and understand it without problems
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();
The result is:
Bar::testPrivate
Foo::testPublic
But now redefine the test () method in the class foo
class Bar{
public function test() {
echo '<br>Im Bar::test';
$this->testPrivate();
$this->testPublic();
}
public function testPublic() {
echo "<br>Bar::testPublic\n";
}
private function testPrivate() {
echo "<br>Bar::testPrivate\n";
}
}
class Foo extends Bar{
public function test() {
echo '<br>Im Foo::test';
$this->testPrivate();
$this->testPublic();
}
public function testPublic() {
echo "<br>Foo::testPublic\n";
}
private function testPrivate() {
echo "<br>Foo::testPrivate\n";
}
}
$myFoo = new Foo();
$myFoo->test();
The result is:
Im Foo::test
Foo::testPrivate
Foo::testPublic
php allows me to override the private method testPrivate (), Why?
Why not? It's difficult to answer that question as it's just how PHP works. If you want to prohibit your methods from being overwritten then you can use the final keyword.
Additionally, in your example, if you do not declare the private method within Foo, you will get an error as Foo technically has no definition for that method. Extending classes have no visibility of any private properties or methods within their parent class.

Please help me with this oop code on php.net site

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

Is there any way to access Base Class Property via Derived Class object directly in PHP

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

Categories