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 !!";
}
}
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();
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.
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.
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
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.
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.
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.";
}
}
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 !!";
}
}
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);
}
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
here is the class structure. I want Observer:callme() to be callable from Children too.
class Observer
{
protected callme()
{
}
}
class Parent extends Observer
{
function createChild()
{
$this->callme(); // this is OK
return new Child ($this);
}
}
class Child
{
private $this myParent;
public function __constructor ($myParent)
{
$this->myParent = $myParent;
}
public function __destroy()
{
$this->myParent->callme(); // FAIL!
}
}
so how to make FAIL work? (without making it public, because its only for used inside "Parent" and its "Children")
The problem is that a protected method is only accessed from the same class or the class children. What you can do is extend your Child class from Parent, like this:
class Child extends Parent
{
public function __constructor ()
{
parent::__constructor();
}
public function __destroy()
{
$this->callme(); // Should work!
}
}
Or just change the method to public.
And, btw, is this code some kind of real code that you will use? That constructor receiving the parent object seems to be so wrong. What are you trying to accomplish?
protected means that you can call that method only from the same class and from subclasses. What you want to do is not possible. The protected keyword would be pointless if you could call these methods from everywhere.
In C++ there is the friend keyword to achieve what you want: you could define Child as friend of Observer (this has to be done from within Observer), and then you can call all methods in Observer (including private and protected) from within methods of Child. But such a keyword does not exist for PHP.
My comment on your question explains why it doesn't work. This answer shows a way to accomplish what you asked based upon your clarification that MyChild should not extend MyParent.
This is a hack example that makes it work by exploiting the fact that php doesn't care if you call protected methods on other instances than yourself as long as you share the ancestor of the protected method.
I had to change the code some to make it valid php. __constructor is not the name of a php constructor.
hacky.php
<?php
class Observer
{
protected function callme()
{
echo 'I was called from ' . get_called_class(), PHP_EOL;
}
}
class MyParent extends Observer
{
public function createMyChild()
{
$this->callme(); // this is OK
return new MyChild ($this);
}
}
class MyChild extends Observer // hackey extends
{
private $myMyParent;
public function __construct($myMyParent)
{
$this->myMyParent = $myMyParent;
$this->myMyParent->callme();
}
}
$p = new MyParent;
$c = $p->createMyChild();
Result:
$ php hacky.php
I was called from MyParent
I was called from MyParent
I think I found the solution:
class Parent extends Observer
{
function createChild()
{
$this->callme(); // this is OK
return new Child (function() { $this->callme(); });
}
}
class Child
{
private $gatewayFunction;
public function __constructor (Closure $gatewayFunction)
{
$this->gatewayFunction = $gatewayFunction;
}
public function __destroy()
{
$this->gatewayFunction->__invoke();
}
}
Who is going to crap himself? :)
class TopParent
{
protected function foo()
{
$this->bar();
}
private function bar()
{
echo 'Bar';
}
}
class MidParent extends TopParent
{
protected function foo()
{
$this->midMethod();
parent::foo();
}
public function midMethod()
{
echo 'Mid';
}
public function generalMethod()
{
echo 'General';
}
}
Now the question is if I have a class, that extends MidParent because I need to call
class Target extends MidParent
{
//How to override this method to return TopParent::foo(); ?
protected function foo()
{
}
}
So I need to do this:
$mid = new MidParent();
$mid->foo(); // MidBar
$taget = new Target();
$target->generalMethod(); // General
$target->foo(); // Bar
UPDATE
Top parent is ActiveRecord class, mid is my model object. I want to use model in yii ConsoleApplication. I use 'user' module in this model, and console app doesn't support this module. So I need to override method afterFind, where user module is called. So the Target class is the class that overrides some methods from model which uses some modules that console application doesn't support.
Try this (http://php.net/manual/en/language.oop5.final.php - not allow to overriding in the childrens):
final protected function foo()
{
$this->midMethod();
parent::foo();
}
in class MidParent and the class Target can't overrides this method.
Directly - you can't. This is how OOP works.
You can do it by a little redesign, e.g. in MidParent add method:
protected function parentFoo()
{
parent::foo();
}
and in Target:
public function foo()
{
$this->parentFoo();
}
But, again, this is only a workaround to solve your question and not a solution.
Actually, you can do this like this way with Reflection::getParentClass():
class Foo
{
public function test($x, $y)
{
echo(sprintf('I am test of Foo with %s, %s'.PHP_EOL, $x, $y));
}
}
class Bar extends Foo
{
public function test()
{
echo('I am test of Bar'.PHP_EOL);
parent::test();
}
}
class Baz extends Bar
{
public function test()
{
$class = new ReflectionClass(get_class($this));
return call_user_func_array(
[$class->getParentClass()->getParentClass()->getName(), 'test'],
func_get_args()
);
}
}
$obj = new Baz();
$obj->test('bee', 'feo'); //I am test of Foo with bee, feo
-but this is an architecture smell in any case. If you need something like this, that should tell you: you're doing something wrong. I don't want to recommend anyone to use this way, but since it's possible - here it is.
#AnatoliyGusarov, your question is interesting and in a sense you can achieve what you desire using yii and php advances features like Traits and Traits in Yii.
Given that it depends on what version of php you are using.However in yii you can achieve this by behaviors and check this SOQ.
In a nutshell you have to use language advanced features or YII framework features to come around this kind of issues,but that boils down to actual requirements
My Class is independant from another Class.
Inside my Class, a function is doing the same but refined job as a function in another Class. Can I use parent:: function_in_another_class() and get my function join that parent funciton's job flow?
No.
In PHP you can only extend from none or one class. As you write both classes are independent to each other, there is no information where to find the one or the other class.
But what you're looking for is probably this:
class A
{
function myFunction() {}
}
class B
{
private $a;
public function __construct(A $a)
{
$this->a = $a;
}
public function myFunction()
{
$this->a->myFunction();
}
}
If any class method already doing the same thing why would you bother call join it?
You can not do it. If you want the same job flow best way to do is to instantiate the other class and invoke that very same method. Thats why we use OOP.
See the example,
interface Fable()
{
public function f();
}
class OtherClass implements Fable
{
public function f()
{
// job flow
}
}
class MyClass
{
private $fable;
public function __construct(Fable $f)
{
$this->fable = $f;
}
public function method1($args){
return $this->fable->f($args);
}
}
If the current class is a child of another class, yes, you can. parent references to the parent class.
From php.net:
<?php
class A {
function example() {
echo "I am A::example() and provide basic functionality.<br />\n";
}
}
class B extends A {
function example() {
echo "I am B::example() and provide additional functionality.<br />\n";
parent::example();
}
}
$b = new B;
// This will call B::example(), which will in turn call A::example().
$b->example();
?>
The best you can do here is to extend Class B from Class A
Class B extends Class A
But, you can also:
class ClassA {
function do_something($args) {
// Do something
}
}
class ClassB {
function do_something_inclassA($args) {
classA::do_something($args);
}
}
Important: calling classa::do_something(); is a static call, in other words with error reporting E_STRICT you will get a static notice warning because function do_something() is not static function do_something()
Also, calling this function statically (i.e. classa::do_something()) means that class a's function cannot refer to $this within it
Suppose both base and son class have a method method_1,
and there's another method method_2 of base.
inside base::method_2,how can I point $this->method_1 to base::method_1 no matter whether $this is a instance of base or son?
If I understand you correctly, you want something like this:
<?php
class base {
public function method1() {
echo "base:method1\n";
}
public function method2() {
if(get_class($this) == 'base') {
$this->method1();
}
else {
parent::method1();
}
echo "base:method2\n";
}
}
class son extends base {
public function method1() {
echo "son:method1\n";
}
}
$obj = new son();
$obj->method2();
where the call to method2 would always use the base version of the method1.
The best way I could do it is as above, but this code won't work since base has no parent. I'm pretty sure what you're trying to do isn't possible.
This is the error you will get:
PHP Fatal error: Cannot access parent:: when current class scope has no parent in
This will do what you want. Props to dbers for the example code (even if his didn't quite work).
<?php
class base {
public function method1() {
echo "base::method1\n";
}
public function method2() {
if (get_parent_class($this) === FALSE) {
echo get_class($this)." has no parent\n";
$this->method1();
} else {
echo get_class($this)." has parent\n";
call_user_func(array(get_parent_class($this), 'method1'));
}
}
}
class son extends base {
public function method1() {
echo "son::method1\n";
}
}
$b = new base();
$b->method2();
$s = new son();
$s->method2();
?>
Outputs:
base has no parent
base::method1
son has parent
base::method1
Make the function private:
<?php
class A
{
public function __construct()
{
$this->foo();
$this->bar();
}
private function foo() { echo "A::foo()\n"; }
public function bar() { echo "A::bar()\n"; }
}
class B extends A
{
public function foo() { echo "B::foo()\n"; }
public function bar() { echo "B::bar()\n"; }
}
new B();
?>
The output is:
A::foo()
B::bar()
Yes it does. It's singular (one parent).
son->method_1 can add to or override ALL of base->method_1 functionality.
son->method_1 can simply add an additional function, and utilize the rest of the functionality of it's parent's instance of method_1
So calling $this->method_1 would use base->method_1, and son->method_1 as long as what you want to use from base isn't overridden in son.
If you call a method that doesn't exist in your subclass, PHP will traverse the class hierarchy until it finds an ancestor class which implements the function you want. This means that if your son class doesn't implement method_2, PHP will automatically look for the nearest ancestor which does. In your case, it will call method_2 of base as you want.
If you are overriding the method_2 in your son class, and you want to do your own implementation of method_2 and also call the base::method_2 implementation then you can use the parent keyword:
class son extends base {
public function method_2() {
parent::method_2();
//do son::method_2()-specific stuff here
}
}
You can't chain parent calls together, so if base was a subclass of GrandparentClass you couldn't do something like this:
parent::parent::method_2(); // trying to call grandparent::method_2
// but this call will fail
But you can directly refer to ancestor classes by name, so this would work:
GrandparentClass::method_2();
And just to take it a little further, there is also a function called class_parents() which returns an array of every ancestor class your class inherits from. This could help if you wanted to go back, say, two ancestors, but you didn't know its specific name for some reason, you could still call the function using eval().
For example, this code would call GrandparentClass::method_2() without directly referencing the class by name in your code:
$parents = class_parents($this);
eval(end($parents) . "::method_2();");
Hope that helps.
As the title states, I'm trying to make a method in a parent class required. Although, I suppose it could be any class. For instance:
class Parent
{
function foo ()
{
// do stuff
}
}
class Child extends Parent
{
function bar ()
{
// do stuff after foo() has ran
}
}
Basically, I want foo() to be required to run or Child class doesn't run and returns an error or redirects to a different page. I could call the function, but I'm wondering If I can make it a requirement when extending the parent class.
If you leverage abstract classes and methods, you can force subclasses to implement the missing methods.
abstract class ParentClass
{
public function foo ()
{
// do stuff
$this->bar();
}
abstract protected function bar();
}
class Child extends ParentClass
{
protected function bar()
{
// does stuff
}
}
Subclasses that don't implement bar() will generate a fatal error.
What you should probably do is override Parent::foo() and then call the parent method in the overridden method like so:
class Parent
{
function foo ()
{
// do stuff
}
}
class Child extends Parent
{
function foo ()
{
if(!parent::foo()) {
throw new Exception('Foo failed');
}
// do child class stuff
}
}
Why not just set a boolean in function foo() that acts as a flag. Check to see if it has been set in the child class/functions, and you're all set.
Have the child call the function from the parent in the construct.
class Child extends Parent
{
function bar ()
{
// do stuff after foo() has ran
}
function __construct(){
parent::foo();
}
}
As already mentioned, it sounds like you want foo() to be abstract, forcing child classes to override it.
Any class containing an abstract class in PHP requires your parent class to be abstract too. This means it can't be instantiated (constructed), only derived / sub-classed. If you try to instantiate an abstract class the compiler will issue a fatal error.
http://php.net/manual/en/language.oop5.abstract.php
See the code in Peter Bailey's answer.
If you're not actually initializing any code within parent class you should use an object interface. Interface methods have to be implemented or the script will throw a fetal error.
More information on them can be found: http://us3.php.net/interface.
I think this might be the only way of implementing such functionality, as I don't think there is a built in solution.
class Parent
{
public $foo_accessed = FALSE;
function foo ()
{
$this->foo_accessed=TRUE;
// do stuff
}
}
class Child extends Parent
{
function bar ()
{
if($this->foo_accessed==TRUE) {
// do stuff after foo() has ran
} else {
// throw an error
}
}
}
Do not depend on other methods. Make sure they've ran.
class Parent
{
function foo()
{
// do stuff
}
}
class Child extends Parent
{
private function bar()
{
// do child class stuff
}
public function doFooBar()
{
parent::foo();
$this->bar();
}
}
Following approach will only ever complain after all processing has been done - however if that is fair to you it will definately make sure foo() has been called in the parent class or otherwise trigger a condition that you can act upon.
class DemandingParent {
private $hasFooBeenCalled = false;
public function foo() {
$this->hasFooBeenCalled = true;
/* do Stuff */
}
public function __destruct() {
if (!$this->hasFooBeenCalled) {
throw new Exception("Naughty Child! Call your parent's foo b4 you speak up!");
}
}
}