Is there any polymorphism in PHP?
Suppose both base
and son
class hav开发者_运维问答e 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.
精彩评论