Есть ли в PHP перегрузка методов?

Ответ

В PHP нет перегрузки методов (method overloading) в классическом виде, как в Java или C++, где можно определить несколько методов с одним именем, но разными сигнатурами параметров.

Однако есть два подхода для достижения похожего поведения:

  1. Использование магических методов __call() и __callStatic(): Они перехватывают вызовы несуществующих методов.

    class MathOperations {
        public function __call($name, $arguments) {
            if ($name === 'sum') {
                // Эмулируем перегрузку: sum() может принимать разное число аргументов
                return array_sum($arguments);
            }
            throw new BadMethodCallException("Method $name does not exist.");
        }
    }
    
    $math = new MathOperations();
    echo $math->sum(1, 2); // 3
    echo $math->sum(1, 2, 3, 4); // 10
  2. Методы с аргументами по умолчанию и вариадическими функциями: Можно создать один метод, который обрабатывает разные случаи.

    class Formatter {
        // Один метод обрабатывает разные сценарии
        public function format($data, string $style = 'default') {
            if (is_array($data)) {
                return $this->formatArray($data, $style);
            }
            if (is_numeric($data)) {
                return $this->formatNumber($data, $style);
            }
            return (string) $data;
        }
        // ... приватные методы formatArray, formatNumber
    }

Начиная с PHP 8, с объединёнными типами (union types) и именованными аргументами (named arguments) возможности для создания гибких API стали ещё лучше, уменьшив практическую необходимость в классической перегрузке.

Ответ 18+ 🔞

Ну, слушай, вот история про PHP и перегрузку методов — просто ёперный театр какой-то. В других языках, типа Java, всё просто: хочешь два метода с одним именем, но разными параметрами — хуй с горы, делаешь и всё работает. А в PHP — нихуя. Там такой классической перегрузки, чтобы прямо несколько методов с разными сигнатурами, — нету, блядь.

Но наши люди не лыком шиты, нашли два подхода, чтобы выкрутиться. Первый — это магические методы __call() и __callStatic(). Они ловят вызовы к несуществующим методам, как хитрая жопа. Представь, ты вызываешь метод, которого нет, а PHP такой: «Ага, ща я тебя поймаю, сука!» И ты уже внутри __call() можешь делать что хочешь.

class MathOperations {
    public function __call($name, $arguments) {
        if ($name === 'sum') {
            // Эмулируем перегрузку: sum() может принимать разное число аргументов
            return array_sum($arguments);
        }
        throw new BadMethodCallException("Method $name does not exist.");
    }
}

$math = new MathOperations();
echo $math->sum(1, 2); // 3
echo $math->sum(1, 2, 3, 4); // 10

Смотри, какой фокус: ты вызываешь sum() с двумя аргументами — работает. С четырьмя — тоже работает. А всё потому, что на самом деле это не отдельные методы, а один __call(), который ловит всё, как манда с ушами, и сам разбирает аргументы. Удобно, но, бля, доверия к такой магии — ебать ноль, потому что если накосячить в логике, то отладка превратится в пиздец.

Второй подход — более прямолинейный, без магии. Берёшь один метод, а внутри него уже смотришь, что тебе пришло, и ветвишь логику. Можно использовать аргументы по умолчанию или вариадические функции (это когда три точки ...). Получается один метод, который жрёт всё подряд, как сосалка.

class Formatter {
    // Один метод обрабатывает разные сценарии
    public function format($data, string $style = 'default') {
        if (is_array($data)) {
            return $this->formatArray($data, $style);
        }
        if (is_numeric($data)) {
            return $this->formatNumber($data, $style);
        }
        return (string) $data;
    }
    // ... приватные методы formatArray, formatNumber
}

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

А с PHP 8 вообще жизнь стала проще, я тебе скажу. Появились объединённые типы и именованные аргументы. Теперь можно сделать один метод, который принимает кучу всего, и при этом явно указать, что он ждёт, например, int|float|array. А вызывать его можно, явно указывая имена параметров, чтобы не путаться. Так что необходимость в классической перегрузке, честно говоря, почти отпала. Но знать про эти костыли всё равно надо — вдруг попадётся легаси-код, написанный, будто на дворе 2002-й год, вот тогда и пригодится.