Вызов статического метода из класса B (который расширяет класс A) класса A - PullRequest
5 голосов
/ 05 февраля 2009

В практическом тесте был интересный вопрос, на который я не понял ответа. Что выводит следующий код:

<?php
class Foo {
    public $name = 'Andrew';

    public function getName() {
        echo $this->name;
    }
}

class Bar extends Foo {
    public $name = 'John';

    public function getName() {
        Foo::getName();
    }
}

$a = new Bar;
$a->getName();
?>

Изначально я думал, что это приведет к ошибке, потому что статические методы не могут ссылаться на $ this (по крайней мере, в PHP5). Я сам проверил это, и он действительно выводит Джона.

Я добавил Foo :: getName (); в конце сценария и получил ошибку, которую я ожидал. Итак, что меняется, когда вы вызываете статический метод из класса, который расширяет класс, из которого вы вызываете?

Кто-нибудь возражает объяснить подробно, что здесь происходит?

Ответы [ 5 ]

7 голосов
/ 05 февраля 2009

Foo :: getName () использует более старый стиль PHP4 оператор разрешения области действия , чтобы разрешить вызов переопределенного метода.

В PHP5 вы бы использовали parent :: getName () вместо

Это полезно, если вы хотите расширить, а не полностью переопределить поведение базового класса, например это может прояснить ситуацию

class Bar extends Foo {
    public $name = 'John';

    public function getName() {
        echo "My name is ";
        parent::getName();
    }
}
4 голосов
/ 05 февраля 2009

Если вы вызываете статический метод, привязанный к другому объекту, метод выполняется в контексте текущего объекта. Который разрешает доступ к объекту $ this-.

Лучший способ вызвать метод суперкласса внутри подкласса:

parent::getName();
2 голосов
/ 05 февраля 2009

$ это объект, в контексте которого был вызван метод. Итак: $ this это $ a-> getName () это $ a. $ this в $ fooInstance-> getName () будет $ fooInstance. В случае, если $ this установлено (при вызове метода объекта $ a) и мы вызываем статический метод, $ this остается присвоенным $ a.

Похоже, что использование этой функции может привести к путанице. :)

1 голос
/ 05 февраля 2009

Иногда программисты лучше объясняют вещи в коде, чем на английском!

Первое, что здесь происходит, это концепция перегрузки. Когда вы создаете экземпляр Bar, его метод getName () перегружает метод с тем же именем в Foo.

Перегрузка является мощной и важной частью OOD.

Однако часто полезно иметь возможность вызывать версию метода, существующего в классе Parent (Foo).

Вот пример:

class Dog
{
   public function getTag()
   {
      return "I'm a dog.";
   }
}

class Skip extends dog
{
   public function getTag()
   {
      return Dog::getTag() . " My name is Skip.";
      // I'm using Dog:: because it matches your example. However, you should use parent:: instead.
   }
}

$o = new Skip();
echo $o->getTag(); // Echo's: "I'm a dog. My name is Skip."

Ясно, что это очень местный пример, но он иллюстрирует точку.

Ваш базовый класс является наиболее общей реализацией типа. В данном случае это «Собака». Вы хотите поместить в этот базовый класс информацию, общую для всех экземпляров этого типа. Это предотвращает дублирование в каждом из производных классов (например, «Пропустить»).

Ваш сценарий использует эту функцию, возможно, случайно.

1 голос
/ 05 февраля 2009

Когда вы вызываете $a->getName(), вы ссылаетесь на определенный объект, $a, который относится к классу Bar и поэтому возвращает "Джон".

Foo::getName() недопустимо вне функции, потому что нет определенного объекта.

Я не уверен, что это работает в PHP, но если вы приведете объект к суперклассу, как в (Foo)$a->getName(), вы получите "Andrew" в качестве результата. Вы бы все еще говорили о конкретном объекте ($a), но в этом случае типа Foo. ( Обратите внимание, что вы вообще не хотите этого делать )

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