PHP: How to call function of a child class from parent class

PhpInheritance

Php Problem Overview


How do i call a function of a child class from parent class? Consider this:

class whale
{
  function __construct()
  {
    // some code here
  }

  function myfunc()
  {
  // how do i call the "test" function of fish class here??
  }
}

class fish extends whale
{
  function __construct()
  {
    parent::construct();
  }

  function test()
  {
    echo "So you managed to call me !!";
  }

}

Php Solutions


Solution 1 - Php

That's what abstract classes are for. An abstract class basically says: Whoever is inheriting from me, must have this function (or these functions).

abstract class whale
{

  function __construct()
  {
    // some code here
  }

  function myfunc()
  {
    $this->test();
  }
  
  abstract function test();
}


class fish extends whale
{
  function __construct()
  {
    parent::__construct();
  }

  function test()
  {
    echo "So you managed to call me !!";
  }

}


$fish = new fish();
$fish->test();
$fish->myfunc();

Solution 2 - Php

Okay, this answer is VERY late, but why didn't anybody think of this?

Class A{
    function call_child_method(){
        if(method_exists($this, 'child_method')){
            $this->child_method();
        }
    }
}

And the method is defined in the extending class:

Class B extends A{
    function child_method(){
        echo 'I am the child method!';
    }
}

So with the following code:

$test = new B();
$test->call_child_method();

The output will be:

I am a child method!

I use this to call hook methods which can be defined by a child class but don't have to be.

Solution 3 - Php

Technically, you cannot call a fish instance (child) from a whale instance (parent), but since you are dealing with inheritance, myFunc() will be available in your fish instance anyway, so you can call $yourFishInstance->myFunc() directly.

If you are refering to the template method pattern, then just write $this->test() as the method body. Calling myFunc() from a fish instance will delegate the call to test() in the fish instance. But again, no calling from a whale instance to a fish instance.

On a sidenote, a whale is a mammal and not a fish ;)

Solution 4 - Php

Since PHP 5.3 you can use the static keyword to call a method from the called class. i.e.:

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // Here comes Late Static Bindings
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test();
?>

The above example will output: B

source: PHP.net / Late Static Bindings

Solution 5 - Php

Ok, well there are so many things wrong with this question I don't really know where to start.

Firstly, fish aren't whales and whales aren't fish. Whales are mammals.

Secondly, if you want to call a function in a child class from a parent class that doesn't exist in your parent class then your abstraction is seriously flawed and you should rethink it from scratch.

Third, in PHP you could just do:

function myfunc() {
  $this->test();
}

In an instance of whale it will cause an error. In an instance of fish it should work.

Solution 6 - Php

I'd go with the abstract class....
but in PHP you don't have to use them to make it work. Even the invocation of the parent class' constructor is a "normal" method call and the object is fully "operational" at this point, i.e. $this "knows" about all the members, inherited or not.

class Foo
{
  public function __construct() {
    echo "Foo::__construct()\n";
    $this->init();
  }
}

class Bar extends Foo
{
  public function __construct() {
    echo "Bar::__construct()\n";
    parent::__construct();
  }
  
  public function init() {
    echo "Bar::init()\n";
  }
}

$b = new Bar;

prints

Bar::__construct()
Foo::__construct()
Bar::init()

i.e. even though class Foo doesn't know anything about a function init() it can call the method since the lookup is based on what $this is a reference to.
That's the technical side. But you really should enforce the implementation of that method by either making it abstract (forcing descendants to implement it) or by providing a default implementation that can be overwritten.

Solution 7 - Php

I know this is probably a bit late for you, but I had to get around this problem as well. To help others understand why this is sometimes a requirement, here's my example:

I'm building an MVC framework for an application, I have a base controller class, which is extended by each individual controller class. Each controller will have different methods, depending on what the controller needs to do. Eg, mysite.com/event would load the event controller. mysite.com/event/create will load the event controller and call the 'create' method. In order to standardise the calling of the create function, we need the base controller class to access the methods of the child class, which will be different for every controller. So code-wise, we have the parent class:

class controller {

	protected $aRequestBits;
	
	public function __construct($urlSegments) {
		array_shift($urlSegments);
		$this->urlSegments = $urlSegments;		
	}
	
	public function RunAction($child) {
		$FunctionToRun = $this->urlSegments[0];
		if(method_exists($child,$FunctionToRun)) {
			$child->$FunctionToRun();
		}
	}	
}

Then the child class:

class wordcontroller extends controller {
		
	public function add() {
		echo "Inside Add";
	}
	
	public function edit() {
		echo "Inside Edit";
	}
	
	public function delete() {
		echo "Inside Delete";
	}
}

So the solution in my case was to pass the child instance itself back to the parent class as a parameter.

Solution 8 - Php

The only way you could do this would be through reflection. However, reflection is expensive and should only be used when necessary.

The true problem here is that a parent class should never rely on the existence of a child class method. This is a guiding principle of OOD, and indicates that there is a serious flaw in your design.

If your parent class is dependent on a specific child, then it cannot be used by any other child classes that might extend it as well. The parent-child relationship goes from abstraction to specificity, not the other way around. You would be much, much better off to put the required function in the parent class instead, and override it in the child classes if necessary. Something like this:

class whale
{
  function myfunc()
  {
      echo "I am a ".get_class($this);
  }
}

class fish extends whale
{
  function myfunc()
  {
     echo "I am always a fish.";
  }
}

Solution 9 - Php

It's very simple. You can do this without abstract class.

class whale
{
  function __construct()
  {
    // some code here
  }

  /*
  Child overridden this function, so child function will get called by parent. 
  I'm using this kind of techniques and working perfectly.  
  */
  function test(){
     return "";
  }

  function myfunc()
  {
    $this->test();
  }
}

class fish extends whale
{
  function __construct()
  {
    parent::construct();
  }

  function test()
  {
    echo "So you managed to call me !!";
  }

}

Solution 10 - Php

Even if this is an old question, this is my solution using ReflectionMethod:

class whale
{
  function __construct()
  {
    // some code here
  }

  function myfunc()
  {
    //Get the class name
    $name = get_called_class();
    
    //Create a ReflectionMethod using the class and method name
    $reflection = new \ReflectionMethod($class, 'test');

    //Call the method
    $reflection->invoke($this);
  }
}

The benefit of using the ReflectionMethod class is that you could pass an array of arguments and check which one is needed in the method you are calling:

    //Pass a list of arguments as an associative array
    function myfunc($arguments){
      //Get the class name
      $name = get_called_class();
    
      //Create a ReflectionMethod using the class and method name
      $reflection = new \ReflectionMethod($class, 'test');
    
      //Get a list of parameters
      $parameters = $reflection->getParameters()

      //Prepare argument list
      $list = array();
      foreach($parameters as $param){

          //Get the argument name
          $name = $param->getName();
          if(!array_key_exists($name, $arguments) && !$param->isOptional())
            throw new \BadMethodCallException(sprintf('Missing parameter %s in method %s::%s!', $name, $class, $method));

          //Set parameter
          $list[$name] = $arguments[$name];
        }
    
      //Call the method
      $reflection->invokeArgs($this, $list);
    }

Solution 11 - Php

From whale instance you can't call this function. but from fish instance you can do

function myfunc()
{
    static::test();
}

Solution 12 - Php

If exists a method in the child class, method will be called from the parent class (as an optional callback if exists)

<?php

    class controller
    {

        public function saveChanges($data)
        {
            //save changes code
            // Insert, update ... after ... check if exists callback
            if (method_exists($this, 'saveChangesCallback')) {
                $arguments = array('data' => $data);
                call_user_func_array(array($this, 'saveChangesCallback'), $arguments);
            }
        }
    }

    class mycontroller extends controller
    {

        public function setData($data)
        {
            // Call parent::saveChanges
            $this->saveChanges($data);
        }

        public function saveChangesCallback($data)
        {
            //after parent::saveChanges call, this function will be called if exists on this child
            // This will show data and all methods called by chronological order:
            var_dump($data);
            echo "<br><br><b>Steps:</b><pre>";
            print_r(array_reverse(debug_backtrace()));
            echo "</pre>";
        }
    }

$mycontroller = new mycontroller();
$mycontroller->setData(array('code' => 1, 'description' => 'Example'));

Solution 13 - Php

That's a little tricky if you talk about OOP concepts that's not possible

but if you use your brain then it can be :)

OOP say's you cannot call child class function from parent class and that's correct because inheritance is made of inheriting parent functions in child

but

you can achieve this with Static class

class Parent
{
  static function test()
  {
     HelperThread::$tempClass::useMe();
  }
}

class child extends parent 
{
  // you need to call this. functon everytime you want to use 
  static function init()
  {
     HelperThread::$tempClass = self::class;
  }

  static function useMe()
  {
     echo "Ahh. thank God you manage a way to use me";
  } 

}

class HelperThread
{
  public static  $tempClass;
}

that's just a solution to my problem. i hope it helps with your problem

Happy Coding :)

Solution 14 - Php

what if whale isn't extended? what would that function call result in? Unfortunately there is no way to do it.

Oh, and does a fish extend a whale? A fish is a fish, a whale is a mammal.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSarfrazView Question on Stackoverflow
Solution 1 - PhpFlorianHView Answer on Stackoverflow
Solution 2 - PhpChristian EngelView Answer on Stackoverflow
Solution 3 - PhpGordonView Answer on Stackoverflow
Solution 4 - PhpAgustinView Answer on Stackoverflow
Solution 5 - PhpcletusView Answer on Stackoverflow
Solution 6 - PhpVolkerKView Answer on Stackoverflow
Solution 7 - Phprca86View Answer on Stackoverflow
Solution 8 - PhpzombatView Answer on Stackoverflow
Solution 9 - Phprishad2m8View Answer on Stackoverflow
Solution 10 - PhpgpmaccariView Answer on Stackoverflow
Solution 11 - PhpSohagView Answer on Stackoverflow
Solution 12 - PhpXPerezView Answer on Stackoverflow
Solution 13 - PhpMr TalhaView Answer on Stackoverflow
Solution 14 - PhpMariusView Answer on Stackoverflow