Можно ли в классе оставить два метода с одинаковым именем, но разной сигнатурой (перегрузка методов)?

Ответ

Нет, в PHP нельзя иметь в одном классе несколько методов с одинаковым именем, даже если у них разные сигнатуры (количество или типы параметров). Попытка объявить такой метод вызовет фатальную ошибку Fatal error: Cannot redeclare ClassName::methodName().

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

Обходные пути и решения:

  1. Использование аргументов по умолчанию и проверок внутри метода:

    class Processor {
        public function process($data, string $mode = 'default') {
            if (is_array($data)) {
                // Обработка массива
            } elseif (is_string($data)) {
                // Обработка строки
            }
            // Дополнительная логика в зависимости от $mode
        }
    }
  2. Использование магического метода __call() для динамической диспетчеризации:

    class DynamicHandler {
        public function __call($name, $arguments) {
            if ($name === 'handle') {
                if (count($arguments) === 1) {
                    return $this->handleSingle($arguments[0]);
                } elseif (count($arguments) === 2) {
                    return $this->handleDouble($arguments[0], $arguments[1]);
                }
            }
            trigger_error('Method not found', E_USER_ERROR);
        }
    
        private function handleSingle($arg) { /* ... */ }
        private function handleDouble($arg1, $arg2) { /* ... */ }
    }
  3. Разрешение конфликтов при использовании трейтов (если методы пришли из разных трейтов):

    trait FormatterA {
        public function format($data) { return json_encode($data); }
    }
    trait FormatterB {
        public function format($data) { return serialize($data); }
    }
    
    class MyClass {
        use FormatterA, FormatterB {
            FormatterA::format insteadof FormatterB; // Используем format из FormatterA
            FormatterB::format as formatSerialized;   // Переименовываем format из FormatterB
        }
    }

Ответ 18+ 🔞

Да ты глянь, какая дичь! В PHP, блядь, ни в коем случае нельзя запихнуть в один класс несколько методов с одним и тем же именем, даже если у них там аргументы разные. Попробуешь — получишь прямо в лоб фатальную ошибку Fatal error: Cannot redeclare ClassName::methodName(). Ядрёна вошь, прям как будто на дворе 2002-й год, а не язык с кучей фич!

Тут, ёпта, нету этой вашей перегрузки методов, как в Java. Вообще. Ноль ебать доверия к такой возможности.

Но народ не лыком шит, обходные пути придумал, конечно:

  1. Аргументы по умолчанию и ручные проверки внутри одного метода — классика жанра. Просто делаешь один метод, а внутри уже смотришь, что тебе прилетело. Хитрая жопа, но работает.

    class Processor {
        public function process($data, string $mode = 'default') {
            if (is_array($data)) {
                // Обработка массива
            } elseif (is_string($data)) {
                // Обработка строки
            }
            // Дополнительная логика в зависимости от $mode
        }
    }
  2. Волшебный метод __call() — для любителей динамики и непредсказуемости. Через него можно ловить вызовы несуществующих методов и творить что хочешь. Главное — не запутаться самому, а то будет пиздопроебибна.

    class DynamicHandler {
        public function __call($name, $arguments) {
            if ($name === 'handle') {
                if (count($arguments) === 1) {
                    return $this->handleSingle($arguments[0]);
                } elseif (count($arguments) === 2) {
                    return $this->handleDouble($arguments[0], $arguments[1]);
                }
            }
            trigger_error('Method not found', E_USER_ERROR);
        }
    
        private function handleSingle($arg) { /* ... */ }
        private function handleDouble($arg1, $arg2) { /* ... */ }
    }
  3. Разборки с трейтами, если методы наложились друг на друга. Бывает, подключаешь два трейта, а в них методы с одинаковыми именами — ёперный театр! Но и тут выход есть: можно указать, какой метод использовать, а какой переименовать, чтобы не было конфликта.

    trait FormatterA {
        public function format($data) { return json_encode($data); }
    }
    trait FormatterB {
        public function format($data) { return serialize($data); }
    }
    
    class MyClass {
        use FormatterA, FormatterB {
            FormatterA::format insteadof FormatterB; // Берём format из FormatterA
            FormatterB::format as formatSerialized;   // А format из FormatterB зовём по-другому
        }
    }

    Вот такие пироги, чувак. Язык, может, и не даёт перегрузку из коробки, но извернуться всегда можно, было бы желание.