简体   繁体   中英

PHP call super parent method

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.

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:

Using trait:

<?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"

Using interface:

<?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"

我可以将“ A”抽象为东西,然后让b和c覆盖它

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM