Calling Parent Class Methods
How can I fix the Base_Text_Is::CammelCase() method without calling the Base_Text class statically (not using parent:: or Base_Text:: )? The only solution I came up with for this kind of situations is to create a singleton function like this:
function Base() < static $instance = null; if (is_null($instance) === true) < $instance = new Base(); >return $instance; >
return ($string === Base()->Text->CammelCase($string));
$base = new Base(); $base->Text->Is->CammelCase('MethodOverloading'); // true
Base()->Text->Is->CammelCase('MethodOverloading'); // true
I don’t get your last comment in Darrell’s answer. You are not able to access Base_Text ‘s non static properties? From where do you want to call them? I think you should explain this further.
@Felix: I’m trying to keep the example as simple as possible, there are cases when I cannot call a parent method statically because it depends on instantiated properties.
2 Answers 2
The heart of your question lies here:
How can Son::B() call the Dad::A() method non-statically (without using parent or Dad)?
The answer is simply, it can’t. You overrode Dad::A() with Son::A() . The only concept of A() that the Son object now has is it’s own A() . You would have to call the parent method statically, or on an altogether different Dad object instance.
The bottom line is, if you want to call the parent A() method, why are you bothering to override it in the first place?
Your structure doesn’t make any sense either. Why would you want a call to $dad->A() pass it to $dad->son->A() , which in turn would call $dad->son->B() , which would then, from what you’re asking, call $dad->A() again? That’s an infinite loop.
Your singleton approach doesn’t seem to offer any real advantage other than making sure you don’t instantiate more than one dad object, but the fact is you’re still instantiating an entirely separate object to perform logic that sounds like it should be inside the class and not outside.
Without seeing actual logic and what you’re trying to accomplish, it’s hard to know what to recommend to avoid this circular reliance. However, I think you might want to analyze what you’re trying to do with these methods and perhaps redesign how the inheritance is working.
I think you’ve got way too much inheritance going on. There is no reason you should be doing this:
$base = new Base(); $base->Text->Is->CammelCase('MethodOverloading'); // true
If all the functionality is in the child classes, you shouldn’t be instantiating the Base class. It should be something like this:
$text = new Text(); $text->isCamelCase('someString');
Your code can be greatly simplified, with all the circular parent/child instantiations removed and the specific functionality pushed down to the child classes:
class Base < //don't put anything related to child classes here, //unless it is going to provide specific functionality >class Text extends Base < public function CamelCase($string) < return trim(str_replace(' ', '', ucwords($string))); >public function isCamelCase($string) < return ($string === $this->CamelCase($string)); > >
PHP Inheritance
Summary: in this tutorial, you will learn about the PHP inheritance that allows a class to reuse the code from another class.
Introduction to the PHP inheritance
Inheritance allows a class to reuse the code from another class without duplicating it.
In inheritance, you have a parent class with properties and methods, and a child class can use the code from the parent class.
Inheritance allows you to write the code in the parent class and use it in both parent and child classes.
The parent class is also called a base class or super class. And the child class is also known as a derived class or a subclass.
To define a class inherits from another class, you use the extends keyword.
Suppose that you have a class called BankAccount as follows:
class BankAccount < private $balance; public function getBalance() < return $this->balance; > public function deposit($amount) < if ($amount > 0) < $this->balance += $amount; > return $this; > >
Code language: HTML, XML (xml)
The BankAccount class has the private property $balance and the public methods getBalance() and deposit() .
To declare that the SavingAccount inherits from the BankAccount , you use the extends keyword as follows:
class SavingAccount extends BankAccount
Code language: HTML, XML (xml)
In this example, the SavingAccount can reuse all the non-private properties and methods from the BankAccount class.
The following creates a new instance of the SavingAccount class, calls the deposit() method and shows the balance:
require 'SavingAccount.php'; $account = new SavingAccount(); $account->deposit(100); echo $account->getBalance();
Code language: HTML, XML (xml)
In this example, the SavingAccount class reuses the properties and methods from the BankAccount class.
A child class can reuse properties and methods from the parent class. But the parent class cannot use properties and methods from the child class.
Add properties and methods to the child class
A child class can have its own properties and methods. In the following example, we add the $interestRate property and setInterestRate() method to the SavingAccount class:
class SavingAccount extends BankAccount < private $interestRate; public function setInterestRate($interestRate) < $this->interestRate = $interestRate; > >
Code language: HTML, XML (xml)
Call methods from the parent class
To call a method from the parent class, you use the $this keyword.
The following example defines the addInterest() method that calculates the interest and adds it to the balance:
class SavingAccount extends BankAccount < private $interestRate; public function setInterestRate($interestRate) < $this->interestRate = $interestRate; > public function addInterest() < // calculate interest $interest = $this->interestRate * $this->getBalance(); // deposit interest to the balance $this->deposit($interest); > >
Code language: HTML, XML (xml)
In the addInterest() method, we call the getBalance() method from the BankAccount class for calculating the interest and the deposit() method to add the interest to the balance.
class BankAccount < private $balance; public function getBalance() < return $this->balance; > public function deposit($amount) < if ($amount > 0) < $this->balance += $amount; > return $this; > > class SavingAccount extends BankAccount < private $interestRate; public function setInterestRate($interestRate) < $this->interestRate = $interestRate; > public function addInterest() < // calculate interest $interest = $this->interestRate * $this->getBalance(); // deposit interest to the balance $this->deposit($interest); > > $account = new SavingAccount(); $account->deposit(100); // set interest rate $account->setInterestRate(0.05); $account->addInterest(); echo $account->getBalance();
Code language: HTML, XML (xml)
Inhertiance and UML
You use the open arrow from the child class to the parent class to represent the inheritance relationship. The following UML diagram shows the inheritance relationship between the BankAccount and SavingAccount classes:
Summary
- Inheritance allows a class to reuse the code of another class without duplicating it.
- Use the extends keyword to define one class that inherits from another class.
- A class that inherits another class is called a subclass, a child class, or a derived class. The class from which the subclass inherits is a parent class, a superclass, or a base class.
- A subclass can have its own properties and methods.
- Use $this keyword to call the methods of the parent class from methods in the child class.
PHP call parent class method
If you want to get down and dirty with Reflection then it’s possible, but I’d strongly argue that this shouldn’t be used anywhere near any production code. If you’ve got an instance of a child class, then you’ve got it for a reason, and if it’s overridden a parent method then that has also happened for a reason.
Assuming you already know all this, then with that disclaimer out of the way, this should work in any remotely recent version of PHP:
class Foo < public function func() < echo 'I am the parent'; >> class Bar extends Foo < public function func() < echo 'I am the child'; >> // Create instance of child class $bar = new Bar; // Create reflection class $reflected = new ReflectionClass(get_class($bar)); // Get parent method $method = $reflected->getParentClass()->getMethod('func'); // Invoke method on child object $method->invokeArgs($bar, []); // I am the parent
That is it. Thank you. I guessed there is some solution with reflections. I have to agree that it is little dirty however less dirty than copying values to parent class object.
This to me looks like a design issue more than anything else. However if I were to handle this in a way that were easily readable and without rethinking my design I would do:
> class Bar extends Foo < public function func() < return 'bar'; >public function parentFunc() < return parent::func(); >> $obj = new Bar(); $obj->parentFunc(); // returns of course 'foo'
Loek’s answer also works, but doesn’t call the method on the objects parent. It just calls the method on the classes parent. It all depends on the functionality you are looking for.
You could also do something like:
> class Bar extends Foo < public function func($parent = false) < if ($parent) < return parent::func(); >return 'bar'; > > $obj = new Bar(); $obj->func(true); // returns of course 'foo'
Which is similar but without the need for the extra method.
Personally though I feel this issue likely requires a rethink in code design more than a coding solution.
To elaborate on ‘a rethink in code design’, I would ask myself «Why do I need an object that has two methods with the same name, but different functionalities? Is this not a job for two different objects? Trace the issue backwards until you find the design issue. Or the point at which the decision needs to be made as to which object your framework requires.
multiple ways of calling parent method in php
At first I was confused why both of the method calls in the constructor work, but now I think I understand. The extending classes inherit the parent’s methods as if they were declared in the class itself, AND the methods exist in the parent, so both should work. Now I’m wondering if there is a preferred way (i.e. best practice) of calling the method (via parent or this ), and whether or not these are truly identical ways of executing the same code, or if there are any caveats when using one over the other. Sorry, I’m probably over thinking this.
abstract class Animal < function get_species() < echo "test"; >> class Dog extends Animal < function __construct()< $this->get_species(); parent::get_species(); > > $spike = new Dog;
2 Answers 2
There are three scenarios (that I can think of) where you would call a method in a subclass where the method exists in the parent class:
This is the same as your example, and generally it’s better to use $this->get_species(); You are right that in this case the two are effectively the same, but the method has been inherited by the subclass, so there is no reason to differentiate. By using $this you stay consistent between inherited methods and locally declared methods.
In this case, you would obviously want to use $this->get_species(); because you don’t want the parent’s version of the method executed. Again, by consistently using $this , you don’t need to worry about the distinction between this case and the first.
In this case, you still want to use $this->get_species(); when calling the method from other methods of the subclass. The one place you will call the parent method would be from the method that is overwriting the parent method. Example:
abstract class Animal < function get_species() < echo "I am an animal."; >> class Dog extends Animal < function __construct()< $this->get_species(); > function get_species() < parent::get_species(); echo "More specifically, I am a dog."; >>
The only scenario I can imagine where you would need to call the parent method directly outside of the overriding method would be if they did two different things and you knew you needed the parent’s version of the method, not the local. This shouldn’t be the case, but if it did present itself, the clean way to approach this would be to create a new method with a name like get_parentSpecies() where all it does is call the parent method:
function get_parentSpecies()
Again, this keeps everything nice and consistent, allowing for changes/modifications to the local method rather than relying on the parent method.