I'm not sure at all if there is such a term but here is what I want to do
class A {
function a($a) {
return $a;
}
}
class B extends A {
function a($a) {
return parent::a('B' . $a);
}
}
class C extends B {
function a($a) {
return superparent::a('C' . $a);
}
}
$c = new C();
echo $c->a('C'); // "CC"
I want to bypass all medial classes and call the function on the parent where it was defined for the first time - is this possible?
No, and it's a terrible idea. All your class C
knows is that it extends B
. It cannot know nor should it know what, if anything, B
extends. C
cannot count on B
extending anything, nor should it be aware of specific methods of that grand parent and their implementation details. You may be refactoring B
tomorrow to extend another class, or to extend no class at all. Code would start breaking left and right if you established such three-class-crossover dependencies.
Classes should only interact with peers they're directly associated with, either through inheritance or dependency injection.
Just logically speaking: B
adds something necessary to the behaviour of A
to "make it a B
", and C
adds something to make it a C
. C
builds on B
, so anything B
does C
should do as well. Having C
"jump over" B
back to A
suggests that your logic and responsibility assignment is mixed up in your class hierarchy.
i thing you can make "A" as abstract, then let b and c override it
You can choose which parent method you call with A::a('C' . $a)
.
When calling a parent function like this, it does not call it statically, just like parent::a()
.
Despite of any Engineering Software complaint (what you are trying to do is something that must be achieved by some other approach) I thought that my both examples were suposed to work:
<?php
trait Bypass_trait {
public function super_ref() {
return parent::super_ref();
}
}
class A {
function a($a) {
return $a;
}
function super_ref() {
return $this;
}
}
class B extends A {
use Bypass_trait;
function a($a) {
return $this->super_ref()->a('B' . $a);
}
}
class C extends B {
use Bypass_trait;
function a($a) {
return $this->super_ref()->a('C' . $a);
}
}
$c = new C();
echo $c->a('C'); // "CC"
<?php
interface Bypass {
public function super_ref();
}
class A implements Bypass {
function a($a) {
return $a;
}
function super_ref() {
return $this;
}
}
class B extends A implements Bypass {
function a($a) {
return $this->super_ref()->a('B' . $a);
}
function super_ref() {
return parent::super_ref();
}
}
class C extends B implements Bypass {
function a($a) {
return $this->super_ref()->a('C' . $a);
}
function super_ref() {
return parent::super_ref();
}
}
$c = new C();
echo $c->a('C'); // "CC"