Есть ли полиморфизм в PHP? - PullRequest
2 голосов
/ 10 апреля 2011

Предположим, что оба класса base и son имеют метод method_1,

и есть другой метод method_2 из base.

внутри base::method_2, как я могу указать $this->method_1 на base::method_1 независимо от того, является ли $this экземпляром base или son?

Ответы [ 5 ]

1 голос
/ 10 апреля 2011

Это будет делать то, что вы хотите. Пропишет в dbers код примера (даже если он не совсем работает).

<?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();

?>

Выходы:

base has no parent
base::method1
son has parent
base::method1
1 голос
/ 10 апреля 2011

Если я вас правильно понимаю, вы хотите что-то вроде этого:

<?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();

, где при вызове method2 всегда будет использоваться базовая версия method1.

Лучший способ сделать это, как описано выше, но этот код не будет работать, так как у base нет родителя. Я почти уверен, что то, что вы пытаетесь сделать, невозможно.

Это ошибка, которую вы получите:

PHP Fatal error:  Cannot access parent:: when current class scope has no parent in 
0 голосов
/ 10 апреля 2011

Если вы вызываете метод, который не существует в вашем подклассе, PHP будет проходить по иерархии классов, пока не найдет класс-предок, который реализует нужную вам функцию. Это означает, что если ваш класс son не реализует method_2, PHP автоматически найдет ближайшего предка, который это сделает. В вашем случае он будет вызывать method_2 из base, как вы хотите.

Если вы переопределяете method_2 в своем классе son и хотите создать собственную реализацию method_2 , а также вызвать реализацию base::method_2 тогда вы можете использовать ключевое слово parent:

class son extends base {
  public function method_2() {
    parent::method_2();
    //do son::method_2()-specific stuff here
  }
}

Вы не можете связывать parent вызовов вместе, поэтому, если base был подклассом GrandparentClass, вы не могли бы сделать что-то вроде этого:

parent::parent::method_2(); // trying to call grandparent::method_2
                            // but this call will fail

Но вы можете напрямую ссылаться на классы предков по имени, так что это будет работать:

GrandparentClass::method_2();

И еще немного подробнее, есть также функция с именем class_parents(), которая возвращает массив каждого класса-предка, от которого унаследован ваш класс. Это может помочь, если вы хотите вернуться, скажем, к двум предкам, но по какой-то причине вы не знаете его конкретного имени, вы все равно можете вызвать функцию, используя eval().

Например, этот код будет вызывать GrandparentClass::method_2() без прямой ссылки на класс по имени в вашем коде:

$parents = class_parents($this);
eval(end($parents) . "::method_2();");

Надеюсь, это поможет.

0 голосов
/ 10 апреля 2011

Да, это так.Это единственное число (один родитель).

son->method_1 может добавить или переопределить ВСЕ функции base->method_1.

son->method_1 может просто добавить дополнительную функцию и использовать оставшуюся частьфункциональность экземпляра его родителя method_1

Таким образом, вызов $this->method_1 будет использовать base->method_1 и son->method_1, пока то, что вы хотите использовать из базы, не будет переопределено в сыне.

0 голосов
/ 10 апреля 2011

Сделать функцию приватной:

<?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();
?>

Вывод:

A::foo()
B::bar()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...