Сигнатуры методов в классе, реализующем интерфейс

Василий М.

Новичок
Сигнатуры методов в классе, реализующем интерфейс, должны точно совпадать с сигнатурами, используемыми в интерфейсе, в противном случае будет вызвана фатальная ошибка.
http://www.php.net/manual/ru/language.oop5.interfaces.php

PHP:
<?php
interface myInterface {
    public function __construct();
}

class concret implements myInterface {

    public function __construct($arg=null)
    {
        print_r(func_get_args());
    }
}

$obj = new concret(123);
?>
ну как этот можно понять логически, умом, догадкой?...
 

Вурдалак

Продвинутый новичок
__construct вообще не должен быть в интерфейсе, это бессмыслица. Тебе нигде не нужно знать про интерфейс конструктора, только в момент создания класса.

Более того, это антипаттерн какой-то.
 
Последнее редактирование:
  • Like
Реакции: riff

Василий М.

Новичок
Почему бессмыслица?

PHP:
<?
// Петя заложил интерфейс конструктора с одним аргументом
interface myInterface {
    public function __construct($arg1);
}

// Вася взял и нарушид интерфейс.
class concret implements myInterface {

    public function __construct($arg1, $arg2=null)
    {
        print_r(func_get_args());
    }
}

$obj = new concret(123, 321);
 

Вурдалак

Продвинутый новичок
Петя — дебил. Не его собачье дело какой будет конструктор, нас не должно это волновать. Интерфейс нужен не на момент создания объекта, а на момент его использования в том коде, где нас не волнует реализация этого объекта, нас интересует только его интерфейс, т.е. где ты пишешь
PHP:
interface UserRepository {
    public function find($id);
    public function findByName($name);
}

class Foo {
    // Здесь уже есть инстанс и нас не волнует конструктор класса
    public function bar(UserRepository $userRepository) {
        $user = $userRepository->findByName('triumvirat');
    }
}
При этом реализации могут тянуть совершенно разные зависимости
PHP:
class PdoUserRepository {
    public function __construct(PDO $pdo) {
        // ...
    }

    // ...
}

class XmlUserRepository {
    public function __construct($xmlFileName) {
        // ...
    }

    // ...
}
Если тебе требуется задать интерфейс конструктору, то ты делаешь что-то не так.
 
Последнее редактирование:

HraKK

Мудак
Команда форума
Вурдалак, в смысле я наверно цитату не совсем корректно вставил, я имел ввиду что если тебе хочется знать интерфейс, то ты не знаешь порождающие паттерны. Я тоже этим страдал, но фабрика, билдер и т. д. решили все мои проблемы.
 

Вурдалак

Продвинутый новичок
Ну да, у него скорее всего имя класса подставляется динамически, это как раз тот случай, когда можно захотеть фиксированный конструктор, а хотеть этого нельзя.

Кстати, static create имеет похожие проблемы, нужно этого избегать. Т.е. некоторые пишут
PHP:
public static function create()
{
    return new static();
}
заранее ограничивая конструктор наследников. Переопределить с другими аргументами это говно потом будет нельзя.
 
Последнее редактирование:

HraKK

Мудак
Команда форума
Василий М., открою тайну, если написать die(); программа прекратит работу, советую подумать как избежать этого. Это более насущая проблема)
 

Вурдалак

Продвинутый новичок
Меня даже больше раздражает new static — некоторые считают, что так писать правильно. На деле — это, по-моему, самообман.
 

Василий М.

Новичок
да хрен с ним, с конструктором. я привел в качестве примера.
на месте конструктора мог бы быть обычный метод.
вопрос остается открытым
данное поведение описанное в первом посте - оно нормально?
 

Вурдалак

Продвинутый новичок
Ну, если никаких ошибок не кидает и не работает, то нет, ненормально. Но это же PHP.
 

riff

Новичок
да хрен с ним, с конструктором. я привел в качестве примера.
на месте конструктора мог бы быть обычный метод.
вопрос остается открытым
данное поведение описанное в первом посте - оно нормально?
Они должны совпадать и точка.
Больше того, php тебе не даст создать extended class с функцией, несовпадающей по параметрам с базовым классом:
Debug Strict (PHP 5): Declaration of B::xxx() should be compatible with A::xxx() in test.php on line ...
точнее предупредит, что это не приветствуется.


UPD: 10 мин спустя, понял, что в данном случае речь может идти не о наследовании, а о двух разных классах, implements один интерфейс, и у них может быть одна функция с разными параметрами.
Так как интерфейсы не умеют перезагружать функции, то должна быть функция2 с другими параметрами, или, если нет возможности влезть в базовый интерфейс, то должен быть "интерфейс2 extended интерфейс1" с доп.функцией.
 
Последнее редактирование:

riff

Новичок
Да, коряво я это всё написал, лучше бы сразу удалил.
Наверно у автора вот такая конструкция.
PHP:
interface myInterface {
    public function myFunction();
}

class Class1 implements myInterface
{
    public function myFunction()
    {
    }
}

class Class2 implements myInterface
{
    public function myFunction($arg=null)
    {
    }
}
Я думаю надо добавить
PHP:
interface myInterface2 extends myInterface {
    public function myFunction2($arg=null);
}
class Class2 implements myInterface2
{
    public function myFunction()
    {
    }
    public function myFunction2($arg=null)
    {
    }
}
 
Последнее редактирование:

hell0w0rd

Продвинутый новичок
А в чем проблема? наследуемый метод по интерфейсу совпадает - никто не обязует передавать в функцию никакие аргументы.
 
Сверху