views:

793

answers:

7

Hi,

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

}
+1  A: 

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.

Marius
that is just an example without thinking much about it :)
Sarfraz
anyways, i could not understand your answer, can u suggest an alternative to it?
Sarfraz
A: 

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.

cletus
+1  A: 

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.";
  }
}
zombat
I doubt it can be done with Reflection. Whale would have to have Fish hardcoded somewhere.
Gordon
that is great info :)
Sarfraz
A: 

You could do:

$food = new fish;
$food->test();
Scott
+1  A: 

Conceptually, fishes cannot extends whales. Whales are mammals. Inheritance indicates an is-a relation, so you are basically saying, a fish is-a whale.

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.

Gordon
this is just an example dude, i am not going to implement those names anywhere :)
Sarfraz
+6  A: 

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();
FlorianH
While correct, I think he wants to do `$whale = new Whale; $fish = new Fish;` and then `$whale->myfunc();` is supposed to call `$fish->test();` without knowing $fish exists.
Gordon
+1, abstract methods are generally the answer to your question of having parent classes refer to methods in child classes. If Gordon is correct and you're really trying to do something different/specific like that, you should clarify. Otherwise, this should be accepted.
philfreo
+1  A: 

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.

VolkerK