Calling parent method of inherited class from base class - php

The following example does not work because when parent is called in class A, php looks for the parent class of class A but it doesn't exist. I would rather this line to call Test() in class B.
Is this possible?
(I know this seems like a stupid example but it has a practical application)
abstract class A {
function CallParentTest()
{
return call_parent_method('Test');
}
}
abstract class B extends A {
function Test()
{
return 'test passed';
}
}
class C extends B {
function Test()
{
return $this->CallParentTest();
}
}
$object = new C();
echo $object->Test();
Thanks!
EDIT
I changed the parent keyword to the made up method call_parent_method because I think that may have been confusing people. I know there is no way to do this using the keyword.
Just as David Harkness pointed out, I am trying to implement the Template Method pattern but instead of using two different method names, I'm using one. B::Test() will be the default method unless substituted with alternate functionality.

You can use reflection to bypass the natural calling order for overridden methods. In any context simply create a ReflectionMethod for the method you'd like to call and invoke it. You don't need to do this from the class itself, but you will need to call setAccessible(true) if the method isn't public.
class A {
public function bypassOverride() {
echo "Hi from A\n";
$r = new ReflectionMethod('B', 'override');
$r->invoke($this);
}
}
class B extends A {
public function override() {
echo "Hi from B\n";
}
}
class C extends B {
public function override() {
echo "Hi from C\n";
$this->bypassOverride();
}
}
$c = new C;
$c->override();
The output from this is
Hi from C
Hi from A
Hi from B
You could make bypassOverride() more generic and move it to a helper class if you need to do this a lot.

Is this possible?
No.
It makes no sense to use the parent keyword except in child classes. It's only purpose is to be used by child classes to call methods that it as overridden. Think about multi-level parent calls where a child calls its parent's method of the same name and, in turn, that parent calls its parent's method of the same name.

webbiedave is correct regarding parent, but it looks like you're trying to implement the Template Method pattern where the abstract base class calls a method that subclasses are expected to implement. Here's an example that demonstrates a horrible way to handle errors in your applications.
abstract class ExceptionIgnorer {
public function doIt() {
try {
$this->actuallyDoIt();
}
catch (Exception $e) {
// ignore the problem and it might go away...
}
}
public abstract function actuallyDoit();
}
class ErrorThrower extends ExceptionIgnorer {
public function actuallyDoIt() {
throw new RuntimeException("This will be ignored");
}
}
$thrower = new ErrorThrower;
$thrower->doIt(); // no problem
Here doIt() is the template method as it defines the overall algorithm to follow.

Related

Calling a child class function if not exist in parent class

I have a code like following ---
class CartItem{
var $v;
function __construct(){
$this->f();
}
function f(){
echo 'In parent';
}
}
class m extends CartItem{
function f(){
echo 'In child';
}
}
new m();
Now when creating instance of m()... it doesn't have any constructor, so it is calling parent classes constructor. Now inside that a function f is called.
What I want is -
if class m() have defined function f()... is should call it instead of parent class's function f().
But anyway it is calling parent classes function, as it was called from parent's constructor, irrespective of child class/ context :(
You want to call in __construct() a method that is not defined in the class. This is a sign that the CartItem class is an abstract concept and you don't intend to instantiate it (because an instance of CartItem probably doesn't contain enough information or behaviour for your project).
An abstract concept is implemented using an abstract class that defines as much as it can and defines abstract methods to be implemented in the concrete classes that extend it. The method f() is such a method that cannot be defined in the abstract concept and has to be defined in each class that extend it:
abstract class CartItem
{
public function __construct()
{
$this->f();
}
abstract protected function f();
}
class m extends CartItem
{
protected function f()
{
// Implement behaviour specific to this class
}
}
This is actually a really interesting question.
so, as I understand it, you're asking (if this isnt right please say):
can you call a function of a class that's extending a parent?
yes, you can... sort of, if the method in the child is static.
Take this example (Ive not used it in the constructor for simplicity of example, but it will work there too):
class ClassA {
public function testMeAsWell() {
return ClassB::testMe();
}
}
class ClassB extends ClassA {
static function testMe() {
return 'do something';
}
}
$child = new ClassB();
echo $child->testMe();
// outputs 'do something'
$parent = new ClassA();
echo $parent->testMeAsWell();
// also outputs 'do something'
the reason this works needs more research, but as a guess I would say that because PHP is compiled, it will know about both classes at run-time and therefore will be able to figure out what we wanted it to do.
So, further on, you want to use variables. Yes you can, but they would have to be static as well.
working example

Call child method from parent class

I have a Class that is used as an extender by several other Classes, and in one instance, a method from the parent Class needs to call back to a method from the child Class. Is there a way of doing this?
I realise PHP contains abstract Classes and functions, but would require each child Class to have the declared abstract function(s), which I do not require in this case.
For example (these are examples, not real life) -
Class parent{
function on_save_changes(){
some_parent_function();
if($_POST['condition'] === 'A') :
// Call 'child_1_action()'
elseif($_POST['condition'] === 'B') :
// Call 'child_2_action()'
endif
some_other_parent_function();
}
function some_parent_function(){
// Do something here, required by multiple child Classes
}
}
Class child_1 Extends parent{
function __construct(){
$this->on_save_changes();
}
function child_1_action(){
// Do something here, only every required by this child Class
}
}
Class child_2 Extends parent{
function __construct(){
$this->on_save_changes();
}
function child_2_action(){
// Do something here, only every required by this child Class
}
}
You can do this by just simply calling the child method, e.g.:
if($_POST['condition'] === 'A') :
$this->some_parent_function();
$this->child_1_action();
However, you should avoid doing this. Putting checks in the parent that call methods only existing in a child class is a very bad design smell. There is always a way to do things in a more structured manner by utilizing well-known design patterns or simply thinking the class hierarchy through better.
A very simple solution you can consider is implementing all of these methods in the parent class as no-ops; each child class can override (and provide implementation for) the method that it's interested in. This is a somewhat mechanical solution so there's no way to know if it's indeed the best approach in your case, but even so it's much better than cold-calling methods that technically are not guaranteed to exist.
Try this:
class ParentClass{
private $childActionMethod;
public function on_save_changes(){
if(method_exists($this, $this->childActionMethod)) {
call_user_func_array(array($this, $this->childActionMethod), func_get_args());
}
else {
throw new Exception('Child Method has not been set');
}
}
protected function setChildActionMethod($methodName) {
$this->childActionMethod = $methodName;
}
}
class ChildClass1 extends ParentClass{
function __construct(){
$this->setChildActionMethod('child_1_action');
}
function child_1_action(){
echo('Hello First World<br />');
}
}
class ChildClass2 extends ParentClass{
function __construct(){
$this->setChildActionMethod('child_2_action');
}
function child_2_action(){
echo('Hello Second World<br />');
}
}
$child1 = new ChildClass1();
$child1->on_save_changes();
// Hello First World
$child2 = new ChildClass2();
$child2->on_save_changes();
// Hello Second World
The parent class has the protected method setChildActionMethod, callable by the children. When the children are instantiated, they tell the parent the name of the method they would like it to call on save.
If the method exists then it is called with any arguments, or it throws an exception (you can change the error handling).
I'm sure theres a name for this pattern, but I am unsure what it is called.
You may use "Template method" pattern, if you need to create some action sequence in parent that child classes should implement on their own but in some predefined manner. But you should avoid referring to future defined arbitrary methods.
In general: any method you use in your parent should be declared either as abstract or have default implementation. Children will override these methods.
abstract class parent{
function on_save_changes(){
some_parent_function();
some_child_action();
some_other_parent_function(); // added to follow changes of question
}
function some_parent_function(){
// Do something here, required by multiple child Classes
}
abstract public function some_child_action();
}
class child_1 Extends parent{
function some_child__action(){
if($_POST['condition'] === 'A') :
// Do something here, only every required by this child Class
endif;
}
}
class child_2 Extends parent{
function some_child_action(){
if($_POST['condition'] === 'B') :
// Do something here, only every required by this child Class
endif;
}
}

Overriding methods in PHP?

In other OO languages like Java we can override a function, possible using keywords/annotations like implements, #override etc.
Is there a way to do so in PHP? I mean, for example:
class myClass {
public static function reImplmentThis() { //this method should be overriden by user
}
}
I want user to implement their own myClass::reImplementThis() method.
How can I do that in PHP? If it is possible, can I make it optional?
I mean, if the user is not implementing the method, can I specify a default method or can I identify that the method is not defined (can I do this using method_exists)?
<?php
abstract class Test
{
abstract protected function test();
protected function anotherTest() {
}
}
class TestTest extends Test
{
protected function test() {
}
}
$test = new TestTest();
?>
This way the class TestTest must override the function test.
Yes, there is. You have the option to override a method by extending the class and defining a method with the same name, function signature and access specifier (either public or protected) it had in the base class. The method should not be declared abstract in the base class or you will be required to implement it in the derived class. In you example it would look something like this:
class MyClass {
public static function reImplmentThis() { //this method should be overriden by user
}
}
class MyDerivedClass extends MyClass {
public static function reImplmentThis() { //the method you want to call
}
}
If the user does not overrides it, MyDerivedClass will still have a reImplmentThis() method, the one inherited from MyClass.
That said, you need to be very careful when invoking extended static methods from your derived class to stay out of trouble. I encourage you to refactor your code to extend instance methods unless you have a very specific need to extend static classes. And if you decide there is no better way than extending static classes please be sure to understand Late Static Binding pretty well.
Yes, its possible to check if the method is implemented or not and get a whole lot more of information about a class using PHP Reflection.
This touches on several OOP subjects.
First, simply overriding an method declared in a parent class is as simple as re-declaring the method in an inheriting class.
E.g:
class Person {
public function greet(string $whom) {
echo "hello $whom!";
}
}
class Tommy extends Person {
public function greet(string $whom = "everyone") {
echo "Howdy $whom! How are you?";
}
}
$a = new Tommy();
$a->greet('World');
// outputs:
// Howdy World! How are you?
If on the overriding method you wan to reuse the logic of the overriden one, it's just a matter of calling the parent's method from the extending class::
class Tommy
{
public function greet(string $whom)
{
// now with more emphasis!!!
echo parent::greet(strtoupper($whom)) . "!!!!";
}
}
Now Tommy::greet() calls Person::greet(), but modifies the result before returning it.
One thing to note is that overriding methods have to be compatible with the overriden one: the method visibility can't be more restrictive than the original one (it's OK to increase visibility), and the number and type of required arguments can't conflict with the original delcaration.
This works, because the type of the arguments does not clash with the original, and we have less required arguments than on the parent:
class Leo extends Person {
public function greet(string $whom = "gorgeous", string $greet = "Whatsup" ) {
echo "$greet $whom. How are you?";
}
}
But this doesn't, since there are additional required arguments. This would make impossible to switch the original class for this one transparently, and thus would throw a Warning:
class BadBob extends Person {
public function greet(string $whom, string $greet ) {
echo "$greet $whom. How are you?";
}
}
Additionally, you mention in your question that "this method should be overriden by the user". If you require client classes to actually implement the method, you have a couple of options:
Abstract classes & methods
These are methods where the implementation is left empty, and that extending classes have to implement to be valid. In we changed our original class Person to:
abstract class Person {
public function greet(string $whom) {
echo "hello $whom!";
}
public abstract function hide();
}
Since now the class contains an abstract method, it needs to be declared as an abstract class as well.
Now it is not possible to instantiate Person directly, you can only extend it in other classes.
Now all our existing Person extending classes would be wrong, and trying to execute the previous code would throw a fatal error.
An example of a valid class extending Person now would be:
class Archie extends Person {
public function hide() {
echo "Hides behind a bush";
}
}
Any class that extends Person must declare a public hide() method.
Interfaces
Finally, you mention interfaces. Interfaces are contracts that implementing classes have to fulfill. They declare a group of public methods without an implementation body.
E.g.:
interface Policeman {
public function arrest(Person $person) : bool;
public function help($what): bool;
}
Now we could have class that extended Person and implemented Policeman:
class Jane extends Person implements Policeman {
public function hide() {
echo "Jane hides in her patrol-car";
}
public function arrest(Person $person): bool{
// implement arrest method
return false;
}
public function shoot($what): bool {
// implements shoot() method
return false;
}
}
Importantly, while it's possible to extend only one class (there is no multiple inheritance in PHP), it is possible to implement multiple interfaces, and the requirements for each of those have to be fulfilled for the class to be valid.

How to run code upon class definition (not object instantiation)

I'm looking for a way to transparently run code when a class is defined - more importantly, when the class is extended.
For example, if I have:
class A
{ function define()
{ echo "A has been defined!\n";
}
__magicDefine
{ define();
}
}
class B extends A
{
}
I'd like that to print "A has been defined!\n". Is this impossible?
That would be impossible, yeah. Nothing gets called on class definition.
This concept is even sort of aggressively unsupported; try writing
class foo {
static function __construct() {
echo "hi!";
}
}
and you'll get Fatal error: Constructor blah::__construct() cannot be static.
I guess what you're trying to do is keep track of objects that are running? Not exactly sure what your end goal is here.
Perhaps you're looking for the ReflectionClass at run time? You can determine if a class exists and what the extended class is.
It also sounds like what you're aiming for is an object factory that keeps track of objects that are being used. Look up singletons, factory, and static member functions/variables concepts for those.
As for this:
class A
{
public function __construct()
{ print "A has been called";
}
}
if class B overrides the constructor, it's not going to call A's constructor. Ex:
class B extends A
{
public function __construct()
{ print "B has been called";
// parent::__construct(); /// would print out A has been called
}
}
However in code, you can check if B is an instance of A one of many ways:
function doSomethingWithA(A $a)....
function doSmoethingWithA($a)
{
if($a instanceof A)
{
// blah
}
}
Don't know if that helps much.
In Java, this is possible, by using a "java agent" which would register a java.lang.instrument.ClassFileTransformer with the JVM.

Can I extend a class using more than 1 class in PHP?

If I have several classes with functions that I need but want to store separately for organisation, can I extend a class to have both?
i.e. class a extends b extends c
edit: I know how to extend classes one at a time, but I'm looking for a method to instantly extend a class using multiple base classes - AFAIK you can't do this in PHP but there should be ways around it without resorting to class c extends b, class b extends a
If you really want to fake multiple inheritance in PHP 5.3, you can use the magic function __call().
This is ugly though it works from class A user's point of view :
class B {
public function method_from_b($s) {
echo $s;
}
}
class C {
public function method_from_c($s) {
echo $s;
}
}
class A extends B
{
private $c;
public function __construct()
{
$this->c = new C;
}
// fake "extends C" using magic function
public function __call($method, $args)
{
$this->c->$method($args[0]);
}
}
$a = new A;
$a->method_from_b("abc");
$a->method_from_c("def");
Prints "abcdef"
You cannot have a class that extends two base classes. You could not have the following:
// this is NOT allowed (for all you google speeders)
Matron extends Nurse, HumanEntity
You could however have a hierarchy as follows...
Matron extends Nurse
Consultant extends Doctor
Nurse extends HumanEntity
Doctor extends HumanEntity
HumanEntity extends DatabaseTable
DatabaseTable extends AbstractTable
and so on.
You could use traits, which, hopefully, will be available from PHP 5.4.
Traits is a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. The semantics of the combination of Traits and classes is defined in a way, which reduces complexity and avoids the typical problems associated with multiple inheritance and Mixins.
They are recognized for their potential in supporting better composition and reuse, hence their integration in newer versions of languages such as Perl 6, Squeak, Scala, Slate and Fortress. Traits have also been ported to Java and C#.
More information: https://wiki.php.net/rfc/traits
Classes are not meant to be just collections of methods. A class is supposed to represent an abstract concept, with both state (fields) and behaviour (methods) which changes the state. Using inheritance just to get some desired behaviour sounds like bad OO design, and exactly the reason why many languages disallow multiple inheritance: in order to prevent "spaghetti inheritance", i.e. extending 3 classes because each has a method you need, and ending up with a class that inherits 100 method and 20 fields, yet only ever uses 5 of them.
There are plans for adding mix-ins soon, I believe.
But until then, go with the accepted answer. You can abstract that out a bit to make an "extendable" class:
class Extendable{
private $extender=array();
public function addExtender(Extender $obj){
$this->extenders[] = $obj;
$obj->setExtendee($this);
}
public function __call($name, $params){
foreach($this->extenders as $extender){
//do reflection to see if extender has this method with this argument count
if (method_exists($extender, $name)){
return call_user_func_array(array($extender, $name), $params);
}
}
}
}
$foo = new Extendable();
$foo->addExtender(new OtherClass());
$foo->other_class_method();
Note that in this model "OtherClass" gets to 'know' about $foo. OtherClass needs to have a public function called "setExtendee" to set up this relationship. Then, if it's methods are invoked from $foo, it can access $foo internally. It will not, however, get access to any private/protected methods/variables like a real extended class would.
Use traits as base classes. Then use them in a parent class. Extend it .
trait business{
function sell(){
}
function buy(){
}
function collectMoney(){
}
}
trait human{
function think(){
}
function speak(){
}
}
class BusinessPerson{
use business;
use human;
// If you have more traits bring more
}
class BusinessWoman extends BusinessPerson{
function getPregnant(){
}
}
$bw = new BusinessWoman();
$bw ->speak();
$bw->getPregnant();
See now business woman logically inherited business and human both;
EDIT: 2020 PHP 5.4+ and 7+
As of PHP 5.4.0 there are "Traits" - you can use more traits in one class, so the final deciding point would be whether you want really an inheritance or you just need some "feature"(trait). Trait is, vaguely said, an already implemented interface that is meant to be just used.
Currently accepted answer by #Franck will work but it is not in fact multiple inheritance but a child instance of class defined out of scope, also there is the `__call()` shorthand - consider using just `$this->childInstance->method(args)` anywhere you need ExternalClass class method in "extended" class.
Exact answer
No you can't, respectively, not really, as manual of extends keyword says:
An extended class is always dependent on a single base class, that is,
multiple inheritance is not supported.
Real answer
However as #adam suggested correctly this does NOT forbids you to use multiple hierarchal inheritance.
You CAN extend one class, with another and another with another and so on...
So pretty simple example on this would be:
class firstInheritance{}
class secondInheritance extends firstInheritance{}
class someFinalClass extends secondInheritance{}
//...and so on...
Important note
As you might have noticed, you can only do multiple(2+) intehritance by hierarchy if you have control over all classes included in the process - that means, you can't apply this solution e.g. with built-in classes or with classes you simply can't edit - if you want to do that, you are left with the #Franck solution - child instances.
...And finally example with some output:
class A{
function a_hi(){
echo "I am a of A".PHP_EOL."<br>".PHP_EOL;
}
}
class B extends A{
function b_hi(){
echo "I am b of B".PHP_EOL."<br>".PHP_EOL;
}
}
class C extends B{
function c_hi(){
echo "I am c of C".PHP_EOL."<br>".PHP_EOL;
}
}
$myTestInstance = new C();
$myTestInstance->a_hi();
$myTestInstance->b_hi();
$myTestInstance->c_hi();
Which outputs
I am a of A
I am b of B
I am c of C
<?php
// what if we want to extend more than one class?
abstract class ExtensionBridge
{
// array containing all the extended classes
private $_exts = array();
public $_this;
function __construct() {$_this = $this;}
public function addExt($object)
{
$this->_exts[]=$object;
}
public function __get($varname)
{
foreach($this->_exts as $ext)
{
if(property_exists($ext,$varname))
return $ext->$varname;
}
}
public function __call($method,$args)
{
foreach($this->_exts as $ext)
{
if(method_exists($ext,$method))
return call_user_method_array($method,$ext,$args);
}
throw new Exception("This Method {$method} doesn't exists");
}
}
class Ext1
{
private $name="";
private $id="";
public function setID($id){$this->id = $id;}
public function setName($name){$this->name = $name;}
public function getID(){return $this->id;}
public function getName(){return $this->name;}
}
class Ext2
{
private $address="";
private $country="";
public function setAddress($address){$this->address = $address;}
public function setCountry($country){$this->country = $country;}
public function getAddress(){return $this->address;}
public function getCountry(){return $this->country;}
}
class Extender extends ExtensionBridge
{
function __construct()
{
parent::addExt(new Ext1());
parent::addExt(new Ext2());
}
public function __toString()
{
return $this->getName().', from: '.$this->getCountry();
}
}
$o = new Extender();
$o->setName("Mahdi");
$o->setCountry("Al-Ahwaz");
echo $o;
?>
I have read several articles discouraging inheritance in projects (as opposed to libraries/frameworks), and encouraging to program agaisnt interfaces, no against implementations.
They also advocate OO by composition: if you need the functions in class a and b, make c having members/fields of this type:
class C
{
private $a, $b;
public function __construct($x, $y)
{
$this->a = new A(42, $x);
$this->b = new B($y);
}
protected function DoSomething()
{
$this->a->Act();
$this->b->Do();
}
}
Multiple inheritance seems to work at the interface level.
I made a test on php 5.6.1.
Here is a working code:
<?php
interface Animal
{
public function sayHello();
}
interface HairyThing
{
public function plush();
}
interface Dog extends Animal, HairyThing
{
public function bark();
}
class Puppy implements Dog
{
public function bark()
{
echo "ouaf";
}
public function sayHello()
{
echo "hello";
}
public function plush()
{
echo "plush";
}
}
echo PHP_VERSION; // 5.6.1
$o = new Puppy();
$o->bark();
$o->plush();
$o->sayHello(); // displays: 5.6.16ouafplushhello
I didn't think that was possible, but I stumbled upon in the SwiftMailer source code, in the Swift_Transport_IoBuffer class, which has the following definition:
interface Swift_Transport_IoBuffer extends Swift_InputByteStream, Swift_OutputByteStream
I didn't play with it yet, but I thought it might be interesting to share.
I just solved my "multiple inheritance" problem with:
class Session {
public $username;
}
class MyServiceResponsetype {
protected $only_avaliable_in_response;
}
class SessionResponse extends MyServiceResponsetype {
/** has shared $only_avaliable_in_response */
public $session;
public function __construct(Session $session) {
$this->session = $session;
}
}
This way I have the power to manipulate session inside a SessionResponse which extends MyServiceResponsetype still being able to handle Session by itself.
If you want to check if a function is public see this topic : https://stackoverflow.com/a/4160928/2226755
And use call_user_func_array(...) method for many or not arguments.
Like this :
class B {
public function method_from_b($s) {
echo $s;
}
}
class C {
public function method_from_c($l, $l1, $l2) {
echo $l.$l1.$l2;
}
}
class A extends B {
private $c;
public function __construct() {
$this->c = new C;
}
public function __call($method, $args) {
if (method_exists($this->c, $method)) {
$reflection = new ReflectionMethod($this->c, $method);
if (!$reflection->isPublic()) {
throw new RuntimeException("Call to not public method ".get_class($this)."::$method()");
}
return call_user_func_array(array($this->c, $method), $args);
} else {
throw new RuntimeException("Call to undefined method ".get_class($this)."::$method()");
}
}
}
$a = new A;
$a->method_from_b("abc");
$a->method_from_c("d", "e", "f");
You are able to do that using Traits in PHP which announced as of PHP 5.4
Here is a quick tutorial for you, http://culttt.com/2014/06/25/php-traits/
One of the problems of PHP as a programming language is the fact that you can only have single inheritance. This means a class can only inherit from one other class.
However, a lot of the time it would be beneficial to inherit from multiple classes. For example, it might be desirable to inherit methods from a couple of different classes in order to prevent code duplication.
This problem can lead to class that has a long family history of inheritance which often does not make sense.
In PHP 5.4 a new feature of the language was added known as Traits. A Trait is kind of like a Mixin in that it allows you to mix Trait classes into an existing class. This means you can reduce code duplication and get the benefits whilst avoiding the problems of multiple inheritance.
Traits
PHP does not yet support multiple class inheritance, it does however support multiple interface inheritance.
See http://www.hudzilla.org/php/6_17_0.php for some examples.
PHP does not allow multiple inheritance, but you can do with implementing multiple interfaces. If the implementation is "heavy", provide skeletal implementation for each interface in a seperate class. Then, you can delegate all interface class to these skeletal implementations via object containment.
Always good idea is to make parent class, with functions ... i.e. add this all functionality to parent.
And "move" all classes that use this hierarchically down. I need - rewrite functions, which are specific.
class A extends B {}
class B extends C {}
Then A has extended both B and C

Categories