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

Viewed 103282

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 !!";
  }

}
14 Answers

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();

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 ;)

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.

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.

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.";
  }
}

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

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

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'));

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 :)

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.

Related