Ответ
Ключевое слово self в PHP используется внутри класса для ссылки на этот же класс. Оно применяется для доступа к статическим свойствам и методам, а также для указания типа возвращаемого значения.
Основные случаи использования:
-
Доступ к статическим членам класса:
class Logger { private static array $logs = []; public static function addLog(string $message): void { self::$logs[] = $message; // self ссылается на класс Logger } } -
Указание типа возвращаемого значения (возврат экземпляра текущего класса):
class Config { public static function getInstance(): self { return new self(); // Создаёт экземпляр Config } }
Критически важное отличие self от static (позднее статическое связывание):
selfвсегда ссылается на класс, в котором оно написано.staticссылается на класс, из которого был вызван метод (позволяет переопределение в дочерних классах).
Наглядный пример различия:
class ParentClass {
public static function createWithSelf(): self {
return new self(); // Всегда вернёт объект ParentClass
}
public static function createWithStatic(): static {
return new static(); // Вернёт объект вызывающего класса
}
}
class ChildClass extends ParentClass {}
var_dump(ChildClass::createWithSelf()); // object(ParentClass)
var_dump(ChildClass::createWithStatic()); // object(ChildClass)
Когда использовать self:
- Когда вам гарантированно нужен экземпляр или статический член именно текущего класса, а не его наследника.
- Для фабричных методов, которые должны создавать объекты определённого, фиксированного класса.
Когда использовать static:
- Для реализации шаблона «Фабричный метод», где каждый наследник должен создавать свой собственный экземпляр.
- В абстрактных классах или трейтах, где логика должна работать с классом-потомком.
Ответ 18+ 🔞
Давай разберём этот ваш self, а то народ путается, как последний идиот. Сидит, блядь, смотрит в монитор, и удивление пиздец — не понимает, почему код не работает. А всё потому, что не видит разницы между self и static. Ёпта, сейчас объясню на пальцах, чтоб даже мартышлюшка поняла.
Вот представь: есть у тебя класс, ну, скажем, Logger. И в нём статическое свойство — массив логов. Так вот, self — это как твоя родная фамилия. Ты где бы ни был, в каком наследнике ни оказался, self всегда будет тыкать пальцем в тот самый класс, где это слово написано в коде. Не там, откуда позвали, а именно там, где его вписали чернилами.
class Logger {
private static array $logs = [];
public static function addLog(string $message): void {
self::$logs[] = $message; // self тут — это навсегда Logger. Точка.
}
}
Второй случай — когда метод должен вернуть объект этого же самого класса. Типа фабричный метод. Опять self — это железное обещание: «Я, сука, верну именно тот тип, в котором объявлен этот метод».
class Config {
public static function getInstance(): self {
return new self(); // Создаст именно Config, даже если вызовут из наследника.
}
}
А теперь, блядь, самое важное, где все и обламываются. Разница между self и static. Это, чувак, как два брата-близнеца: один упёртый и тупой (self), а другой гибкий и умный (static).
self— упёртый. Он смотрит только туда, где его написали. «Я родился в классеParentClass— значит, я всегда буду проParentClass».static— хитрая жопа. Он смотрит, откуда его реально позвали. «Ага, меня вызвали изChildClass— значит, я теперь проChildClass».
Смотри, вот тебе живой пример, после которого всё встанет на свои места:
class ParentClass {
public static function createWithSelf(): self {
return new self(); // Упёртый. Всё равно вернёт ParentClass.
}
public static function createWithStatic(): static {
return new static(); // Хитрый. Вернёт тот класс, откуда позвали.
}
}
class ChildClass extends ParentClass {}
var_dump(ChildClass::createWithSelf()); // object(ParentClass) — вот, бля, сюрприз!
var_dump(ChildClass::createWithStatic()); // object(ChildClass) — вот это уже логично.
Видишь, что происходит? self нихуя не смотрит на то, что ты вызываешь метод из ChildClass. Он как баран упёрся: «Я написан в ParentClass — значит, создаю ParentClass». А static — тот ещё приспособленец, сразу подстраивается под того, кто его кликнул.
Так когда что юзать?
self— когда тебе нахуй не сдались наследники. Ты пишешь железобетонную логику именно для этого класса. Например, у тебя классMySQLConnection, и его фабричный метод должен создавать только его, а не какую-то левую поделку. Или доступ к статике, которая точно определена в этом классе.static— когда ты проектируешь для расширения. Шаблон «Фабричный метод», абстрактные классы, трейты — там, где каждый уважающий себя наследник должен уметь создавать себя самого, а не своего предка. Вот тутstatic— твой лучший друг, иначе будет волнение ебать, когда всё поломается.
Короче, запомни: self — это про «где написано», static — про «откуда вызвано». Всё остальное — от лукавого и непонимания базовых принципов. Не усложняй, иди пиши код.