Ссылка на имя суперкласса PHP с помощью магической константы / ключевого слова или аналогичной конструкции (избегая именования суперкласса в производном классе)

Комментарии в следующем коде показывают, что я пытаюсь выполнить, что очень просто: я хочу иметь возможность ссылаться на имя родительского класса, используя встроенную константу PHP (или другую конструкцию), такую ​​как __CLASS__, но который ссылается на родительский класс, а не на текущий класс (например, parent::__CLASS__) (также, хотя код не показывает это, если у меня есть подкласс, то внутри такого класса я хочу иметь возможность ссылаться на родительский класс через что-то вроде parent::parent::__CLASS__ если вообще возможно).

class ParentClass {

  protected $foo;

  function __construct() {

    $this->foo = "hello";

  }

}

class DerivedClass extends ParentClass {

  public $bar;

  public $baz;

  function __construct($bar) {

    // I want to be able to write
    // something like parent:__CLASS__
    // here in place of 'ParentClass'
    // so that no matter what I rename
    // the parent class, this line will
    // always work. Is this possible?

//      if (is_a($bar, parent::__CLASS__)) {

    if (is_a($bar, 'ParentClass')) {

      $this->bar = $bar;

    } else {

      die("Unexpected.");

    }

    $this->baz = "world";

  }

  public function greet() {

    return $this->bar->foo . " " . $this->baz;

  }

}

$d = new DerivedClass(new ParentClass());
echo $d->greet();

ВЫХОД:

hello world

2 ответа

Решение

Тебе нужно get_parent_class Функция, чтобы сделать это.

function __construct($bar) {

    $parent = get_parent_class($this);


    if (is_a($bar, $parent)) {

      $this->bar = $bar;

    } else {

      die("Unexpected.");

    }

    $this->baz = "world";

  }

если вам нужен дальнейший уровень ниже, вы можете использовать:

class subDerivedClass extents DerivedClass{
    $superParent = get_parent_class(get_parent_class($this));
}

В PHP 5.5 вы можете использовать ключевое слово ::class чтобы получить имя родителя класса, но оно будет работать только a) из класса и b) только на один уровень выше, то есть непосредственный родительский предок:

function __construct($bar) {
   if ($bar instanceof parent::class) {
      ...
   }
}

Лучшее решение, за которое я бы пошел - это цепочка get_parent_class:

if ($bar instanceof get_parent_class(get_parent_class())) {
    ...
}

Или метод цепочки через отражение:

$parent_class = (new Reflection($this))->getParentClass()->getParentClass()->getName();

if ($bar instanceof $parent_class) {
    ...
}
Другие вопросы по тегам