Overloading

Оновлено: 11.05.2023

Перевантаження в PHP надає засоби для динамічного створення властивостей і методів. Ці динамічні сутності обробляються за допомогою магічних методів, які можна створити в класі для різних типів дій.

Перевантажувальні методи викликаються при взаємодії з властивостями або методами, які не були оголошені або не є видимими у поточній області видимості. Далі у цьому розділі будуть використовуватися терміни недоступні властивості та недоступні методи для позначення такої комбінації оголошення та видимості.

Всі методи перевантаження повинні бути визначені як загальнодоступні.

Зауважте:

Жоден з аргументів цих магічних методів не може бути переданий за посиланням.

Зауважте:

Інтерпретація перевантаження в PHP відрізняється від більшості об'єктно-орієнтованих мов. Перевантаження традиційно надає можливість мати декілька методів з однаковими іменами, але різною кількістю і типами аргументів.

__set() виконується при записі даних у недоступні (protected або private) або неіснуючі властивості.

__get() використовується для читання даних з недоступних (protected або private) або неіснуючих властивостей.

__isset() спрацьовує при виклику isset() або empty() для недоступних (захищених або приватних) або неіснуючих властивостей.

__unset() викликається, коли unset() застосовується до недоступних (protected або private) або неіснуючих властивостей.

Аргумент $name - це ім'я властивості, з якою відбувається взаємодія. Аргумент $value методу __set() вказує значення, до якого слід встановити властивість $name'ed.

Перевантаження властивостей працює тільки в контексті об'єкта. Ці магічні методи не спрацьовують у статичному контексті. Тому ці методи не слід оголошувати статичними. Попередження видається, якщо один з магічних методів перевантаження оголошено статичним.

Зауважте:

Значення, що повертається функцією __set(), ігнорується через те, як PHP обробляє оператор присвоювання. Аналогічно, __get() ніколи не викликається при такому ланцюжку присвоєнь:

Зауважте:

PHP не буде викликати перевантажений метод зсередини того ж самого перевантаженого методу. Це означає, що, наприклад, написання return $this->foo всередині __get() поверне null і видасть E_WARNING, якщо властивість foo не визначено, а не викличе __get() вдруге. Однак, методи перевантаження можуть викликати інші методи перевантаження неявно (наприклад, __set() викликає __get()).

Приклад #1 Перевантаження властивостей методами __get(), __set(), __isset() та __unset()

<?php
class PropertyTest
{
    /**  Location for overloaded data.  */
    private $data = array();

    /**  Overloading not used on declared properties.  */
    public $declared = 1;

    /**  Overloading only used on this when accessed outside the class.  */
    private $hidden = 2;

    public function __set($name, $value)
    {
        echo "Setting '$name' to '$value'\n";
        $this->data[$name] = $value;
    }

    public function __get($name)
    {
        echo "Getting '$name'\n";
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }

        $trace = debug_backtrace();
        trigger_error(
            'Undefined property via __get(): ' . $name .
            ' in ' . $trace[0]['file'] .
            ' on line ' . $trace[0]['line'],
            E_USER_NOTICE);
        return null;
    }

    public function __isset($name)
    {
        echo "Is '$name' set?\n";
        return isset($this->data[$name]);
    }

    public function __unset($name)
    {
        echo "Unsetting '$name'\n";
        unset($this->data[$name]);
    }

    /**  Not a magic method, just here for example.  */
    public function getHidden()
    {
        return $this->hidden;
    }
}


echo "<pre>\n";

$obj = new PropertyTest;

$obj->a = 1;
echo $obj->a . "\n\n";

var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";

echo $obj->declared . "\n\n";

echo "Let's experiment with the private property named 'hidden':\n";
echo "Privates are visible inside the class, so __get() not used...\n";
echo $obj->getHidden() . "\n";
echo "Privates not visible outside of class, so __get() is used...\n";
echo $obj->hidden . "\n";
?>

__call() спрацьовує при виклику недоступних методів у контексті об'єкта.

__callStatic() спрацьовує при виклику недоступних методів у статичному контексті.

Аргумент $name - це ім'я методу, що викликається. Аргумент $arguments - це перечислюваний масив, що містить параметри, які передаються до методу $name'ed.

Приклад #2 Перевантаження методів з допомогою методів __call() та __callStatic()

<?php
class MethodTest
{
    public function __call($name, $arguments)
    {
        // Note: value of $name is case sensitive.
        echo "Calling object method '$name' "
             . implode(', ', $arguments). "\n";
    }

    public static function __callStatic($name, $arguments)
    {
        // Note: value of $name is case sensitive.
        echo "Calling static method '$name' "
             . implode(', ', $arguments). "\n";
    }
}

$obj = new MethodTest;
$obj->runTest('in object context');

MethodTest::runTest('in static context');
?>