





По http://www.php.net/manual/en/language.oop5.static.php нет $self. Есть только $this для ссылки на текущий экземпляр класса (объект) и self, который можно использовать для ссылки на статические члены класса. Здесь проявляется разница между экземпляром объекта и классом.
Предложение: прочтите этот ответ, когда наткнетесь на кислоту.
Use
$thisto refer to the current object. Useselfto refer to the current class. In other words, use$this->memberfor non-static members, useself::$memberfor static members.
Вот пример использования правильный$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();
?>
The idea is that
$this->foo()calls thefoo()member function of whatever is the exact type of the current object. If the object is oftype X, it thus callsX::foo(). If the object is oftype Y, it callsY::foo(). But with self::foo(),X::foo()is always called.
От http://www.phpbuilder.com/board/showthread.php?t=10354489:
Автор: http://board.phpbuilder.com/member.php?145249-laserlight
Этот ответ слишком упрощен. Как указано в других ответах, self используется с оператором разрешения области :: для ссылки на текущий класс; это можно сделать как в статическом, так и в нестатическом контексте. Кроме того, совершенно законно использовать $this для вызова статических методов (но не для ссылки на поля).
Также рассмотрите возможность использования static :: вместо :: self, если вы используете версию 5.3+. В противном случае это может вызвать у вас невыразимые головные боли, см. Мой ответ ниже, чтобы узнать, почему.
-1. Этот ответ вводит в заблуждение, прочтите другие ответы для получения дополнительной информации.
Он может быть слишком упрощен, но он ответил на мой вопрос базового уровня, не заставив мою голову взорваться. Я получил дополнительную информацию, которую я нашел полезной в дальнейшем, но пока я просто пытался выяснить, почему я использовал атрибуты своего класса с помощью $ this-> attrib и константы класса с помощью self :: constant. Это помогло мне понять это лучше
Что насчет $this::?
@James Вот как вы вызываете статический метод. Как staticclass :: parse (). Но, как и ваш, наличие $ в имени вашего класса недопустимо.
const MYCONST = 1 defined in non-static classes. Calling $this->MYCONST will trigger an неопределенное свойство notice. The only way to get such value declared inside a non-static (or static) class is to use self::MYCONST.
self (не $ self) относится к тип класса, а $this относится к текущему пример класса. self предназначен для использования в статических функциях-членах, чтобы позволить вам получить доступ к статическим переменным-членам. $this используется в нестатических функциях-членах и является ссылкой на экземпляр класса, для которого была вызвана функция-член.
Поскольку this является объектом, вы используете его как: $this->member
Поскольку self не является объектом, это в основном тип, который автоматически ссылается на текущий класс, вы используете его как: self::member
$this-> используется для ссылки на конкретный экземпляр переменных класса (переменных-членов) или методов.
Example:
$derek = new Person();
$ derek теперь является конкретным экземпляром Person. У каждого человека есть first_name и last_name, но у $ derek есть определенные first_name и last_name (Дерек Мартин). Внутри экземпляра $ derek мы можем ссылаться на них как на $ this-> first_name и $ this-> last_name.
ClassName :: используется для обозначения этого типа класса и его статических переменных, статических методов. Если это поможет, вы можете мысленно заменить слово «статический» на «общий». Поскольку они являются общими, они не могут ссылаться на $ this, которое относится к конкретному экземпляру (не общему). Статические переменные (т. Е. Статические $ db_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 является статическим (общим), он будет отражать общее количество активных объектов базы данных. Возможно, вы видели этот метод, используемый для совместного использования соединений с базой данных среди всех экземпляров класса базы данных. Это сделано потому, что создание соединения с базой данных занимает много времени, поэтому лучше всего создать только одно и поделиться им (это называется одноэлементным шаблоном).
Статические методы (например, общедоступный статический 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);
Как видите, общедоступная статическая функция prettyName ничего не знает об объекте. Он просто работает с параметрами, которые вы передаете, как обычная функция, не являющаяся частью объекта. Зачем тогда беспокоиться, если мы могли бы просто иметь это не как часть объекта?
СЕБЯ:: Если вы кодируете вне объект, который имеет статический метод, на который вы хотите сослаться, вы должны вызвать его, используя имя объекта 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;
Надеюсь, что это поможет прояснить ситуацию :)
Отличный ответ. Я просто хочу указать, что при обращении к статическому атрибуту вам необходимо использовать знак $. Например self::$templates_path
Я считаю, что вопрос заключался не в том, можно ли вызвать статический член класса, вызвав ClassName::staticMember. Вопрос в том, в чем разница между использованием self::classmember и $this->classmember.
Например, оба следующих примера работают без ошибок, независимо от того, используете ли вы self:: или $this->.
class Person{
private $name;
private $address;
public function __construct($new_name,$new_address){
$this->name = $new_name;
$this->address = $new_address;
}
}
class Person{
private $name;
private $address;
public function __construct($new_name,$new_address){
self::$name = $new_name;
self::$address = $new_address;
}
}
Особенно забавно, что вы начинаете свой ответ со слов «Я считаю, что вопрос не в том, можете ли вы вызвать статический член класса, вызвав ClassName :: staticMember. Вопрос был в том, в чем разница между использованием self :: classmember и $ this-> classmember» а затем вы продолжаете, чтобы не показывать вообще никаких различий. Фактически, вы показываете пример того, как эти два варианта работают одинаково. -1
Тем не менее полезно. Объем был связан с разрешением, и эта часть не ясна в руководстве по php. Я все еще считаю это полезным
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
Ключевое слово self не относится к НЕТ просто к «текущему классу», по крайней мере, не таким образом, чтобы ограничивать вас статическими членами. В контексте нестатического члена self также предоставляет способ обхода vtable (см. вики на vtable) для текущего объекта. Так же, как вы можете использовать parent::methodName() для вызова родительской версии функции, вы можете вызвать self::methodName() для вызова реализации метода текущего класса.
class Person {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function getTitle() {
return $this->getName()." the person";
}
public function sayHello() {
echo "Hello, I'm ".$this->getTitle()."<br/>";
}
public function sayGoodbye() {
echo "Goodbye from ".self::getTitle()."<br/>";
}
}
class Geek extends Person {
public function __construct($name) {
parent::__construct($name);
}
public function getTitle() {
return $this->getName()." the geek";
}
}
$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();
Это выведет:
Hello, I'm Ludwig the geek
Goodbye from Ludwig the person
sayHello() использует указатель $this, поэтому vtable вызывается для вызова Geek::getTitle().
sayGoodbye() использует self::getTitle(), поэтому vtable не используется, и вызывается Person::getTitle(). В обоих случаях мы имеем дело с методом созданного объекта и имеем доступ к указателю $this в вызываемых функциях.
Этот ответ был бы даже лучше, если бы вы начали с общего правила, а не с исключения. Это вопрос стиля, а не технических знаний. Это лучший пример разницы между self :: и $ this->, который я когда-либо видел, но стыдно скрывать это, сначала опровергая какое-либо понятие.
@adjwilli: Почему это плохой стиль? Разве это не пробуждает сознание, если ожидание (тезис) ОП сначала отвергается (антитезис), а затем дается объяснение как синтез?
Я считаю "текущий класс" действительно проблематичным. Поскольку это словосочетание можно понимать как «класс, в котором находится self» / «определение класса, который является буквальной частью», так и «класс объекта» (который на самом деле будет static).
Что насчет $this::?
@James - нет веских причин использовать $this::; все возможные случаи уже охвачены более часто используемыми синтаксисами. В зависимости от того, что вы имеете в виду, используйте $this->, self:: или static::.
@ToolmakerSteve Достаточно справедливо. Я просто подумал, есть ли хороший вариант использования или еще одна бессмысленная вещь в PHP со слишком большим пространством для маневра и т. д. Сначала это сбивает с толку, но наверняка будет означать себя из-за двоеточий.
НЕ ИСПОЛЬЗУЙТЕ self::, используйте static::
Есть еще один аспект self ::, о котором стоит упомянуть. Досадно self:: относится к сфере действия в точке определения, а не в точке выполнения. Рассмотрим этот простой класс с двумя методами:
class Person
{
public static function status()
{
self::getStatus();
}
protected static function getStatus()
{
echo "Person is alive";
}
}
Если мы позвоним Person::status(), мы увидим «Человек жив». Теперь посмотрим, что происходит, когда мы создаем класс, наследующий от этого:
class Deceased extends Person
{
protected static function getStatus()
{
echo "Person is deceased";
}
}
Вызывая Deceased::status(), мы ожидаем увидеть «Человек мертв», однако мы видим «Человек жив», поскольку область действия содержит определение исходного метода, когда был определен вызов self::getStatus().
В PHP 5.3 есть решение. оператор разрешения static:: реализует «позднюю статическую привязку», которая представляет собой причудливый способ сказать, что он привязан к области действия вызываемого класса. Измените строку в status() на static::getStatus(), и результаты будут такими, как вы ожидаете. В более старых версиях PHP вам придется найти кладж для этого.
См. Документация PHP
Итак, чтобы ответить на вопрос не так, как задано ...
$this-> относится к текущему объекту (экземпляру класса), тогда как static:: относится к классу
А как насчет констант класса?
«При вызове умершего :: status () мы ожидаем увидеть« Человек мертв »». Нет. Это статический вызов функции, поэтому здесь нет никакого полиморфизма.
Из всех недостатков PHP я, например, не думаю, что это вообще безумие. Как еще они позволили бы кодировщикам назначать методы в текущем классе (в отличие от поиска их в vtable)? Если бы они назвали его по-другому (возможно, с подчеркиванием), то люди, которым нужна эта функция, критиковали бы ее за уродливость. Иначе, какое бы разумное имя они ни использовали, кажется, всегда найдутся люди, которые легко запутаются, которые будут критиковать его за «безумное» поведение, вероятно, не обращая внимания на то, как вообще работает диспетчеризация методов.
Этот пример мне кажется сбивающим с толку: я вижу метод getStatus как метод, который я бы назвал для экземпляра класса, а не для класса.
Пожалуйста, подумайте о редактировании ответа, поскольку php -r "class X { private const X = 1; public static function show() { echo static::X; }} class Y extends X {} Y::show();" выдаст undefined class constant X, поскольку константа не существует в Y. в этом случае требуется self::X (вместо создания const protected, что, к сожалению, можно сделать, если они считают self:: запрещенным).
@Sqoo - сказать, что "НЕ ИСПОЛЬЗУЙТЕ self ::, используйте static ::" - это странная мысль - это умышленно не та же операция. Я думаю, что вы действительно имеете в виду "будет понятнее, если вы используете фактическое имя класса MyClass ::, а не self ::. То есть, если вам нужно поведение self::, вы можете получить это менее запутанно, используя конкретное имя класса, например MyClass::.
Here is an example of correct usage of $this and self for non-static and static member variables:
<?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();
?>
Когда self используется с оператором ::, он относится к текущему классу, что может быть выполнено как в статическом, так и в нестатическом контекстах. $this относится к самому объекту. Кроме того, вполне законно использовать $this для вызова статических методов (но не для обращения к полям).
$this указывает на текущий объект.static относится к текущему объекту.self относится к тому классу, в котором оно было определено.parent относится к родительскому элементу того класса, в котором он был определен.См. Следующий пример, показывающий перегрузку.
<?php
class A {
public static function newStaticClass()
{
return new static;
}
public static function newSelfClass()
{
return new self;
}
public function newThisClass()
{
return new $this;
}
}
class B extends A
{
public function newParentClass()
{
return new parent;
}
}
$b = new B;
var_dump($b::newStaticClass()); // B
var_dump($b::newSelfClass()); // A because self belongs to "A"
var_dump($b->newThisClass()); // B
var_dump($b->newParentClass()); // A
class C extends B
{
public static function newSelfClass()
{
return new self;
}
}
$c = new C;
var_dump($c::newStaticClass()); // C
var_dump($c::newSelfClass()); // C because self now points to "C" class
var_dump($c->newThisClass()); // C
var_dump($b->newParentClass()); // A because parent was defined *way back* in class "B"
В большинстве случаев вы хотите обратиться к текущему классу, поэтому вы используете static или $this. Однако бывают случаи, когда вы необходимостьself, потому что вам нужен исходный класс, независимо от того, что его расширяет. (Очень, очень редко)
Используйте self, если вы хотите вызвать метод класса без создания объекта / экземпляра этого класса, тем самым сохраняя ОЗУ (иногда для этой цели используйте self). Другими словами, он фактически вызывает метод статически. Используйте this для объектной перспективы.
Внутри определения класса $this относится к текущему объекту, а self относится к текущему классу.
Необходимо ссылаться на элемент класса, используя self, и ссылаться на элемент объекта, используя $this.
self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable
selfrefers to the current classselfcan be used to call static functions and reference static member variablesselfcan be used inside static functionsselfcan also turn off polymorphic behavior by bypassing the vtable$thisrefers to the current object$thiscan be used to call static functions$thisshould not be used to call static member variables. Useselfinstead.$thiscan not be used inside static functions
$this относится к объекту текущего класса, self относится к текущему классу (не объекту). Класс - это план объекта. Итак, вы определяете класс, но строите объекты.
Другими словами, используйте self for static и this for none-static members or methods.
также в дочернем / родительском сценарии self / parent в основном используется для идентифицированных дочерних и родительских членов и методов класса.
К тому же $this:: еще не обсуждался.
Только для информационных целей, начиная с PHP 5.3 при работе с экземплярами объектов для получения текущего значения области, в отличие от использования static::, можно альтернативно использовать $this::, как это.
class Foo
{
const NAME = 'Foo';
//Always Foo::NAME (Foo) due to self
protected static $staticName = self::NAME;
public function __construct()
{
echo $this::NAME;
}
public function getStaticName()
{
echo $this::$staticName;
}
}
class Bar extends Foo
{
const NAME = 'FooBar';
/**
* override getStaticName to output Bar::NAME
*/
public function getStaticName()
{
$this::$staticName = $this::NAME;
parent::getStaticName();
}
}
$foo = new Foo; //outputs Foo
$bar = new Bar; //outputs FooBar
$foo->getStaticName(); //outputs Foo
$bar->getStaticName(); //outputs FooBar
$foo->getStaticName(); //outputs FooBar
Использование приведенного выше кода не является общепринятой или рекомендуемой практикой, а просто для иллюстрации его использования и должно действовать как «Знаете ли вы?». в отношении вопроса оригинального плаката.
Он также представляет использование $object::CONSTANT, например echo $foo::NAME;, в отличие от $this::NAME;.
В PHP вы используете ключевое слово self для доступа к статическим свойствам и методам.
Проблема в том, что вы можете заменить $this->method() на self::method() где угодно, независимо от того, объявлен method() статическим или нет. Итак, какой из них вы должны использовать?
Рассмотрим этот код:
class ParentClass {
function test() {
self::who(); // will output 'parent'
$this->who(); // will output 'child'
}
function who() {
echo 'parent';
}
}
class ChildClass extends ParentClass {
function who() {
echo 'child';
}
}
$obj = new ChildClass();
$obj->test();
В этом примере self::who() всегда будет выводить «родительский», а $this->who() будет зависеть от того, какой класс имеет объект.
Теперь мы можем видеть, что self относится к классу, в котором он вызывается, а $this относится к класс текущего объекта.
Таким образом, вы должны использовать self только тогда, когда $this недоступен, или когда вы не хотите, чтобы классы-потомки перезаписывали текущий метод.
Вот небольшой тест (7.2.24 на REPL.IT):
Speed (in seconds) Percentage
$this-> 0.91760206222534 100
self:: 1.0047659873962 109.49909865716
static:: 0.98066782951355 106.87288857386
Всего 4 000 000 прогонов. Вывод: неважно. А вот код, который я использовал:
<?php
class Foo
{
public function calling_this() { $this->called(); }
public function calling_self() { self::called(); }
public function calling_static() { static::called(); }
public static function called() {}
}
$foo = new Foo();
$n = 4000000;
$times = [];
// warmup
for ($i = 0; $i < $n; $i++) { $foo->calling_this(); }
for ($i = 0; $i < $n; $i++) { $foo->calling_self(); }
for ($i = 0; $i < $n; $i++) { $foo->calling_static(); }
$start = microtime(true);
for ($i = 0; $i < $n; $i++) { $foo->calling_this(); }
$times["this"] = microtime(true)-$start;
$start = microtime(true);
for ($i = 0; $i < $n; $i++) { $foo->calling_self(); }
$times["self"] = microtime(true)-$start;
$start = microtime(true);
for ($i = 0; $i < $n; $i++) { $foo->calling_static(); }
$times["static"] = microtime(true)-$start;
$min = min($times);
echo $times["this"] . "\t" . ($times["this"] / $min)*100 . "\n";
echo $times["self"] . "\t" . ($times["self"] / $min)*100 . "\n";
echo $times["static"] . "\t" . ($times["static"] / $min)*100 . "\n";
Вызов бездействующей функции 2 000 000 раз длится 1 с. Должен любить PHP.
Старый добрый PHP. :) Но звонок = 0.001мс. Это так плохо?
Я считаю, что это (и подобные вещи) - вот почему такие вещи, как ORM, кажутся медленными, если вы не кешируете данные, а генераторы статических сайтов - это вещь.
Теоретически он должен занимать 1 такт процессора, что в наши дни составляет около 1 / 2e9 s = 0.5 ns.
Просто перечитай мой ответ. Будьте осторожны: это тоже создает класс. Я не знаю, почему я не использовал ключевое слово use tbh, но у меня больше нет PHP, чтобы повторить тест, и мне не очень хочется его переустанавливать.
Согласно php.net, в этом контексте есть три специальных ключевых слова: self, parent и static. Они используются для доступа к свойствам или методам из определения класса.
$this, с другой стороны, используется для вызова экземпляра и методов любого класса, пока этот класс доступен.
self относится к текущему классу (в котором он называется),
$this ссылается на текущий объект.
Вы можете использовать static вместо self.
См. Пример:
class ParentClass {
function test() {
self::which(); // output 'parent'
$this->which(); // output 'child'
}
function which() {
echo 'parent';
}
}
class ChildClass extends ParentClass {
function which() {
echo 'child';
}
}
$obj = new ChildClass();
$obj->test();
Выход: родитель ребенок
Случай 1: использование self может использоваться для констант класса
class classA {
const FIXED_NUMBER = 4;
self::POUNDS_TO_KILOGRAMS
}
Если вы хотите вызвать его вне класса, используйте classA::POUNDS_TO_KILOGRAMS для доступа к константам
Случай 2: для статических свойств
class classC {
public function __construct() {
self::$_counter++; $this->num = self::$_counter;
}
}
Я столкнулся с тем же вопросом, и простой ответ:
$this требует экземпляр классаself:: не работаетВсякий раз, когда вы используете статические методы или статические атрибуты и хотите вызвать их без создания экземпляра объекта класса, вам необходимо использовать self: для их вызова, потому что $this всегда требует создания объекта.
Ключевое слово себя:: используется для текущего класса и в основном используется для доступа к статическим членам, методам и константам. Но в случае $ это вы не можете вызывать статический член, метод и функции.
Вы можете использовать ключевое слово себя:: в другом классе и получить доступ к статическим членам, методу и константам. Когда он будет расширен из родительского класса и то же самое в случае ключевого слова $ это. Вы можете получить доступ к нестатическим членам, методу и функции в другом классе, когда он будет расширяться от родительского класса.
Приведенный ниже код является примером ключевых слов себя:: и $ это. Просто скопируйте и вставьте код в свой файл кода и посмотрите результат.
class cars{
var $doors=4;
static $car_wheel=4;
public function car_features(){
echo $this->doors." Doors <br>";
echo self::$car_wheel." Wheels <br>";
}
}
class spec extends cars{
function car_spec(){
print(self::$car_wheel." Doors <br>");
print($this->doors." Wheels <br>");
}
}
/********Parent class output*********/
$car = new cars;
print_r($car->car_features());
echo "------------------------<br>";
/********Extend class from another class output**********/
$car_spec_show=new spec;
print($car_spec_show->car_spec());
возможный дубликат Новая личность против новой статики