PHP: Interhited method calling a method in the parent class - php

class Person {
function foo() {
// Code.
}
function bar() {
$this->foo();
}
}
class Pete extends Person {
}
When Person::foo() is called from within Person::bar() in the above example, the call is happening within the Person class. Hence, I could make the visibility of Person::foo() private.
As you'll be aware, when I extend the Person class, Person::foo() and Person::bar() are inherited by the child class Pete. Hence, the inherited method Pete::bar() calls Pete::foo().
My question
From within Pete::bar(), is the call to Pete::foo() considered to come from a) the parent class or b) the child class?

If a method has a visibility of private, then all code which explicitly calls it must reside in the same class definition. That's pretty much the rule, nothing more, nothing less. Indirect calls through inheritance work just fine.
class Foo {
private function bar() { }
public function baz() { /* here be dragons */ }
}
class Child extends Foo { }
In the Child class you may not write $this->bar(). It will fail. The bar method is private to the class Foo, no other code may call it. You may call baz though anytime from anywhere, it is public and can be called from other code. Whatever baz does internally is none of your concern. If baz calls bar internally, that's fine. Its code resides in Foo and therefore can call bar.

From within Pete::bar(), is the call to Pete::foo() considered to come from a) the parent class or b) the child class?
Neither. Technically, foo() does not exist in class Pete. It exists in Person and is inherited by Pete. Regardless, who's calling the method is based on the invocation.
For example:
$person = new Person();
$person->foo(); // invocation by `Person` object
$pete = new Pete();
$pete->foo(); // invocation by `Pete` object
I'm trying to determine method visibility
If you want these methods to be inherited, you are limited to public or protected. private methods are not inherited. I would encourage you to read more about visibility.
As noted in deceze's answer, you can make methods private and access it through another public method.

If you make it private, Person::foo can only be called from Person
class Person {
//Can only be called inside of Person
private function foo() {
// Code.
}
public function bar() {
//can be called
$this->foo();
}
}
You can still call bar, since it is public. bar still can access to foo, because it is a method from Person.
You can not call foo from Pete, since it is only visible in Person.
class Pete extends Person {
public function doSomething() {
//Works because bar itself calls foo
$this->bar();
}
}
If you want to call foo directly fom Pete or override it, you need to declare it protected instead of private.

Related

Inheritance and function calls parent and sub-class

I encountered the following structure:
// parent class
class A
{
public function myFunc1()
{
$this->myFunc2();
}
private function myFunc2()
{
echo "called from class A";
}
}
// sub-class
class B extends A
{
private function myFunc2()
{
echo "called from class B";
}
}
$foo = new B();
$foo->myFunc1();
I expected, since there is no myFunc1() in class B, that the parent-function is called. This seems to be correct.
Now, to play it safe, I var_dump $this in myFunc1() and it shows, that this is an object from type B.
From my understanding, it should call myFunc2() from the Class B, but this isn't happening. It is calling the method from class A.
called from class A
instead of
called from class B
Yes, the functions are private and if I change it to protected, it works as expected. But private implies, that I have access to this function(s), when I'm in the specific context, doesn't it?
Private functions are only available within the class they are defined in, not in sub classes.
This means that your Object has two completely different functions, that happen to have the same name. Object B is aware of having one of them while Object A is only aware of having the other one. They do not interact in any way.
Since these functions are entirely private to the specific class they were defined in, there is no way to override them, or for any other class to call them.
If you need behavior that allows you to override how the class works, you'll have to use protected instead, which is designed specifically to be callable and changeable from extensions (and as such is a completely different beast all-together).
private always belongs to the same class you can't inherit it. That's the reason why myFunc1() calls myFunc2() from class A. If you want to overwrite it you have to change the visibility to protected.

How to force an implementation of a protected static function

I'm trying to write an abstract class (or interface) which forces the extending class to implement a protected static function.
But this is neither possible with an abstract class nor an interface.
Errors:
static functions should not be abstract
access type for interface members must be omitted
Any ideas how to accomplish that?
UPDATE
The purpose is basically to call the public function statically. This way the class does not need to be instanciated.
It is also not necessary to make _doSpecificStuff() callable from class-external code.
abstract class Foo
{
public static function doStuff()
{
[generic code]
static::_doSpecificStuff();
}
// sth like that would be nice to have:
abstract static protected function _doSpecificStuff();
}
From a theoretical as well as a practical standpoint, there's no real need to declare a static method abstract.
Abstract methods are there to have a child class fill in a blank. That's typically because the parent class (the original abstract class) does some generic operation, but can/must be adapted to certain specific situations and can thus force child classes to implement only this particular variable part in the otherwise generic algorithm. Abstract methods are supposed to be a blank spot within a larger algorithm.
A parent method would call implementations of its abstract methods without knowing or caring who implements them or how they're implemented:
abstract class Foo {
public function someAlgo() {
$foo = $this->doSomethingSpecific();
...
}
abstract protected function doSomethingSpecific();
}
Foo doesn't care who or what fills in the blank doSomethingSpecific, it just relies on it being there and its signature, which abstract enforces. The specific object which implements this method or how it implements it is variable. This is important and is at the core of the issue.
Declaring a static method abstract is pretty useless in this scenario. Any static method can just as well be implemented as a non-static method, so there's no use for it here. If the class itself is supposed to call the abstract method as part of a larger generic algorithm as described above, there's no need for a static method.
So the only scenario left for a static method is for a public static method which is callable from anywhere:
abstract class Foo {
abstract public static function bar();
}
class Baz extends Foo {
public static function bar() { ... }
}
Baz::bar();
The thing is, since the abstract class Foo is not itself calling this function but this function is only called from external code, you're not really talking about a fill-in-the-blank method, you're talking about an interface. So, you should be using an interface instead.
But even there, since you have to type the specific class name in your source code, hardcoded, there's little point for an interface as well.
The point of declaring an interface or abstract method signature is that you want to fix the method signature so any code can call that particular method without caring what object it's calling it on in particular. But since you have to hardcode the class name, there's no variability in the object you're calling it on. If you type Baz::bar(), you know exactly what class you're calling what method on. Therefore there's little point in abstracting the interface/signature.
Compare:
interface FooInterface {
public function bar();
}
function baz(FooInterface $foo) {
$foo->bar();
}
The function baz can rely on its argument having a bar() method due to the interface declaration. The specific object that's implementing the method is irrelevant and will vary.
abstract class Foo {
public function someAlgo() {
$foo = $this->doSomethingSpecific();
...
}
abstract protected function doSomethingSpecific();
}
The class Foo can rely on it having the doSomethingSpecific method. The specific object that's implementing the method is irrelevant and will vary.
abstract class Foo {
abstract public static function bar();
}
class Baz extends Foo {
public static function bar() { ... }
}
Baz::bar();
What exactly are you relying on or abstracting here? You can be pretty darn sure Baz will have the method bar() every time, because you're only ever calling it on the same hardcoded class. Nothing is variable here.

How to prevent overriding a superclass by a subclass using final method PHP

I am just learning php and I came across final method, it says it can prevent overriding of a method in the superclass by a subclass. I would like you to please give me some examples of this as the textbook am using didn't explain enough.
For example if you have a superclass let's say Foo. Containing a final method called : bar
class Foo
{
final public function bar()
{
//Do action A
}
}
Now we have a subclass, let's say called Foo2, which extends from Foo.
class Foo2 extends Foo
{
//This class will not be able to override the bar() function.
}
As the final keyword indicated that the function can not be overridden, "Action A" will alway be the stuff the function does, it can not be changed in the subclasses.

Class inheritance - Calling properties and/or methods not in the parent class

I'm trying to understand class inheritance.
Suppose I have the following code (PHP):
class A {
public function fire() {
echo "Fire!";
}
}
class B extends A {
public function water() {
echo "Water!";
}
}
class C extends B {
public function lightning() {
echo "Lightning!";
}
}
$cObject = new C();
$cObject->fire();
My questions are
Even though the fire() method is not defined in class C nor class B, $cObject->fire() works. Does class C inherit not only class B's methods, but class A's methods? I'm trying to find out how many levels deep inheritance will go.
Is there a term for calling a property or method that does not exist in the current object instance, but this property or method exists in a parent or ancestor class? EDIT: In other words, fire() is not defined in class C, but $cObject can still call fire(). Is there any particular term/jargon for this concept? (Or is it just part of the definition of "class inheritance")
I'm trying to find out how many levels deep inheritance will go.
infinetely, if you want. no limits
Is there a term for calling a property or method that does not exist in the current object instance, but this property or method exists in a parent or ancestor class?
For class variables: no.
For class methods: yes. declare them as private:
class A {
private function test() {
echo 'test';
}
}
class B extends A {
public function __construct() {
$this->test();
}
}
$b = new B();
Output:
Fatal error: Call to private method A::test() from context 'B' in /home/thorsten/a.php on line 14
1) Class 'B' is an 'A'. Class 'C' is a 'B', therefor, 'C' is an 'A'. Everything that 'B' has rights and privileges to in 'A', 'C' has as well. C++ has a concept of private inheritance that gets a little funky here, but that's the general idea. As said in the other answer, inheritance will go as far as the chain is defined.
2) I think you meant to ask "What is a function called that is not defined in derived class, but instead in the base class. This type of function is called a virtual function. From what I understand, every class function in PHP is a virtual function and can be overridden (reimplemented in a derived class) unless it is declared as final.

PHP manual OOP visibility example - can someone explain it

I saw this in the PHP OOP manual http://www.php.net/manual/en/language.oop5.visibility.php and I can't get my head around why the output is not: Foo::testPrivate Foo::testPublic
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
It's all about the visibility of the variables / methods.
You'll notice that in the Bar class, the method testPrivate() is private. That means that ONLY itself can access that method. No children.
So when Foo extends Bar, and then asks to run the test() method, it does two things:
It overrides the testPublic() method because it's public, and Foo has the right to override it with it's own version.
It calls test() on Bar (since test() only exists on Bar()).
testPrivate() is not overridden, and is part of the class that holds test(). Therefore, Bar::testPrivate is printed.
testPublic() is overridden, and is part of the inheriting class. Therefore, Foo::testPublic is printed.
In some cases, it is easy to notice that you want a private method on the Bar class, but you also wants the Foo class to access it.
But wait, it is public or private?
Here comes the protected modifier.
When a method is private, only the class itself can call the method.
When a method is public, everyone can call it, like a free party.
When a method is protected, the class itself can call it and also whoever inhered this method (children) will be able to call it as a method of their own.
I posted the same question few days ago... because this behaviour wasnt logical for me either.
$this is always referred to the current object which it is used in. In my opinion example like this should throw an error or warning or something. Because in the above example you are actually accessing private members :SSS WHICH SUPPOSED TO BE INACCESSIBLE!

Categories