Что будет при вызове отсутствующего метода в потомке с помощью self::?

Ответ

При вызове self::отсутствующийМетод() в классе-потомке произойдет фатальная ошибка (Fatal Error). Это происходит потому, что self всегда ссылается на класс, в котором это ключевое слово написано, а не на класс, который его вызывает во время выполнения (потомок).

Пример на PHP:

class ParentClass {
    public static function foo() {
        echo "Parent foon";
    }
}

class ChildClass extends ParentClass {
    public static function bar() {
        // self ссылается на ChildClass, даже если метод вызван из него
        self::missingMethod(); // Фатальная ошибка
    }
}

ChildClass::bar();
// Вывод: Fatal error: Uncaught Error: Call to undefined method ChildClass::missingMethod()

Решение: Для вызова методов с учетом иерархии наследования во время выполнения используйте позднее статическое связывание с static::.

Ответ 18+ 🔞

Давай разберём эту хрень, а то тут, бля, люди путаются как слепые котята в луже. Смотри, есть у тебя класс-родитель и класс-потомок. Всё вроде бы мирно и спокойно, пока ты не начинаешь тыкать в self::отсутствующийМетод().

Вот представь, self — это такой упёртый мудак, который смотрит только туда, где его написали. Он нихуя не смотрит на то, кто его в итоге вызывает. Написали его в классе ChildClass — он и будет тыкать пальцем исключительно в ChildClass, даже если ты зовёшь метод из родителя. А если в ChildClass такого метода нет — всё, приехали. Фатальная ошибка, ядрёна вошь! Программа просто ложится и помирает, как муха в сентябре.

Вот смотри на этот код, тут всё наглядно:

class ParentClass {
    public static function foo() {
        echo "Parent foon";
    }
}

class ChildClass extends ParentClass {
    public static function bar() {
        // self ссылается на ChildClass, даже если метод вызван из него
        self::missingMethod(); // Фатальная ошибка
    }
}

ChildClass::bar();
// Вывод: Fatal error: Uncaught Error: Call to undefined method ChildClass::missingMethod()

Видишь? Мы вызываем bar() у потомка, а self внутри него тупо лезет искать missingMethod() в самом ChildClass. Не находит — и бабах! Тебе в консоль плюёт ошибкой, что метод не определён. Доверия ебать ноль к такому поведению.

А как тогда быть, спросишь ты? А вот как, чувак. Надо использовать не этого упрямого осла self, а его умного брата — static::. Это называется позднее статическое связывание, звучит заумно, а суть проще пареной репы.

static — это хитрая жопа. Он смотрит не на то, где его написали, а на то, какой класс реально вызывает метод в момент выполнения. То есть он поднимается по цепочке наследования и ищет метод там, где он должен быть. Если в потомке нет — полезет в родителя. В общем, ведёт себя как адекватный человек, а не как манда с ушами.

Так что запомни: хочешь, чтобы методы вызывались с учётом всей иерархии наследования — юзай static::. А self:: оставь для тех случаев, когда ты на 146% уверен, что метод есть именно в этом классе, и никуда лезть не надо. Всё, вопрос закрыт.