22

Когда использовать 'self' вместо '$this'?

11

В PHP 5 в чем разница между использованием self и $this?

Когда следует использовать каждый из них?

5 ответ(ов)

19

Краткий ответ

Используйте $this для обращения к текущему объекту. Используйте self для обращения к текущему классу. Другими словами, используйте $this->member для нестатических членов, используйте self::$member для статических членов.

Полный ответ

Вот пример правильного использования $this и self для нестатических и статических переменных-членов:

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?>

Вот пример неправильного использования $this и self для нестатических и статических переменных-членов:

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo self::$non_static_member . ' '
           . $this->static_member;
    }
}

new X();
?>

Вот пример полиморфизма с использованием $this для методов-членов:

<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        $this->foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

Вот пример подавления полиморфного поведения с использованием self для методов-членов:

<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        self::foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

Идея заключается в том, что $this->foo() вызывает метод foo() того типа, который представляет текущий объект. Если объект имеет тип X, то вызывается X::foo(). Если объект имеет тип Y, то вызывается Y::foo(). Однако с self::foo() всегда вызывается X::foo().

Ссылка на источник: http://www.phpbuilder.com/board/showthread.php?t=10354489

Автор: http://board.phpbuilder.com/member.php?145249-laserlight

1

В PHP self (не $self) ссылается на тип класса, тогда как $this ссылается на текущий экземпляр класса. self используется в статических методах для доступа к статическим переменным класса. $this применяется в нестатических методах и представляет собой ссылку на экземпляр класса, на котором был вызван метод.

Так как this является объектом, вы обращаетесь к его членам так: $this->member.

Поскольку self не является объектом, это, по сути, тип, который автоматически ссылается на текущий класс. Вы используете его следующим образом: self::member.

1

$this-> используется для обращения к конкретному объекту класса, его переменным (членам класса) или методам.

$дerek = new Person();

Теперь $дerek является конкретной экземпляром класса Person. У каждого экземпляра Person есть first_name и last_name, но у $derek есть конкретные значения first_name и last_name (Дерек Мартин). Внутри экземпляра $derek мы можем обращаться к этим переменным как $this->first_name и $this->last_name.

ClassName:: используется для обращения к самому классу и его статическим переменным и методам. Чтобы упростить восприятие, можно мысленно заменить слово "статический" на "разделяемый". Поскольку они разделяемые, они не могут обращаться к $this, который ссылается на конкретный экземпляр (не разделяемый). Статические переменные (например, static $db_connection) могут быть общими для всех экземпляров определенного типа объектов. Например, все объекты базы данных могут использовать одно соединение (статическую $connection).

Пример статических переменных: Предположим, у нас есть класс базы данных с одной член-переменной: static $num_connections;. Теперь добавим это в конструктор:

function __construct()
{
    if(!isset($num_connections) || $num_connections == null)
    {
        $num_connections = 0;
    }
    else
    {
        $num_connections++;
    }
}

Так же, как объекты имеют конструкторы, они также имеют деструкторы, которые выполняются, когда объект уничтожается или снимается с учёта:

function __destruct()
{
    $num_connections--;
}

Каждый раз, когда мы создаём новый экземпляр, это увеличивает наш счётчик соединений на единицу. Каждый раз, когда мы уничтожаем или перестаём использовать экземпляр, это уменьшает счётчик соединений на единицу. Таким образом, мы можем отслеживать количество экземпляров объекта базы данных, которые мы используем:

echo DB::num_connections;

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

Статические методы (например, public static View::format_phone_number($digits)) могут вызываться БЕЗ предварительного создания одного из этих объектов (они не ссылаются на $this).

Пример статического метода:

public static function prettyName($first_name, $last_name)
{
    echo ucfirst($first_name).' '.ucfirst($last_name);
}

echo Person::prettyName($derek->first_name, $derek->last_name);

Как видно, public static function prettyName ничего не знает об объекте. Он просто работает с параметрами, которые вы передаете, как обычная функция, не относящаяся к объекту. Почему же тогда это нужно, если мы могли бы просто не делать из этого часть объекта?

  1. Во-первых, привязка функций к объектам помогает поддерживать порядок, так вы всегда будете знать, где их найти.
  2. Во-вторых, это предотвращает конфликты имен. В крупном проекте у вас, вероятно, будет два разработчика, создающих функции getName(). Если один создаст ClassName1::getName(), а другой — ClassName2::getName(), это не вызовет проблем. Нет конфликта. Ура статическим методам!

SELF:: Если вы пишете код вне объекта, к статическому методу которого вы хотите обратиться, вам нужно использовать имя объекта: View::format_phone_number($phone_number); Если вы пишете код внутри объекта, который содержит статический метод, к которому вы хотите обратиться, вы можете использовать ЛИБО имя объекта: View::format_phone_number($pn), ЛИБО использовать сокращение self::format_phone_number($pn).

То же самое относится к статическим переменным: Пример: View::templates_path против self::templates_path.

Внутри класса DB, если мы хотим обратиться к статическому методу другого объекта, мы будем использовать имя этого объекта: Пример: Session::getUsersOnline();

Но если класс DB хочет обратиться к своей собственной статической переменной, он просто скажет self: Пример: self::connection;

0

В PHP ключевое слово self используется для доступа к статическим свойствам и методам.

Проблема заключается в том, что вы можете заменить $this->method() на self::method() в любом месте, независимо от того, объявлен ли method() как статический или нет. Так какой же из этих вариантов следует использовать?

Рассмотрим следующий код:

class ParentClass {
    function test() {
        self::who();    // выведет 'parent'
        $this->who();   // выведет 'child'
    }

    function who() {
        echo 'parent';
    }
}

class ChildClass extends ParentClass {
    function who() {
        echo 'child';
    }
}

$obj = new ChildClass();
$obj->test();

В этом примере self::who() всегда будет выводить «parent», в то время как $this->who() будет зависеть от того, в каком классе находится объект.

Таким образом, мы можем увидеть, что self ссылается на класс, в котором оно было вызвано, тогда как $this ссылается на класс текущего объекта.

Поэтому следует использовать self только тогда, когда $this недоступен или когда вы не хотите позволить дочерним классам переопределить текущий метод.

0

self ссылается на текущий класс (в котором он вызывается), в то время как $this ссылается на текущий объект. Вместо self можно использовать static.

Вот пример:

class ParentClass {
    function test() {
        self::which();    // Выведет 'parent'
        $this->which();   // Выведет 'child'
    }

    function which() {
        echo 'parent';
    }
}

class ChildClass extends ParentClass {
    function which() {
        echo 'child';
    }
}

$obj = new ChildClass();
$obj->test();

Вывод:

parent
child

Таким образом, self всегда будет ссылаться на метод класса, в котором он определен (в данном случае ParentClass), тогда как $this указывает на экземпляр объекта, в котором метод вызывается (в данном случае объект ChildClass).

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь