Чи можна мати інтерфейс, який має приватні / захищені методи?


76

Чи можливо в PHP 5 мати інтерфейс, який має приватні / захищені методи?

Зараз у мене є:

interface iService
{
    private method1();
}

Це видає помилку:

Помилка синтаксичного аналізу: помилка синтаксису, несподіваний T_STRING, очікується T_VARIABLE

Я просто хочу отримати підтвердження того, що інтерфейс може містити лише загальнодоступні методи.


2
Я вважаю відповідь невтішною. Я хотів би інтерфейсів, які також підтримують захищені / приватні методи. Наприклад, у мене є клас, де загальнодоступний метод, реалізований абстрактно, покладається на захищений метод, реалізований підкласом. Я хочу використовувати інтерфейс для вимагання підкласів для реалізації захищених методів, необхідних абстрактним загальнодоступним методам.
Stoutie

4
Для цього використовуйте абстрактний базовий клас. Ви можете поєднати два підходи: загальнодоступні методи в інтерфейсі, реалізація цих методів в абстрактному базовому класі, який визначає (і спирається на) абстрактно захищені методи.
Stijn de Witt

2
Якби ви могли оголосити приватні або захищені методи, було б private function method1 ();НЕ private method1();.
tvanc

Відповіді:



20

Інтерфейси використовуються для опису загальнодоступних методів класу, що реалізує цей інтерфейс. Ви ніколи не можете мати приватний метод в інтерфейсі. Будь-які методи в інтерфейсі вважаються такими, що використовуються, і їх не слід змінювати.

Інтерфейси - це посилання PHP, але це є стандартним для програмування ОО.


1
іншими мовами, такими як Java, ви можете використовувати модифікатори доступу в інтерфейсах.
Користувач123456

9

Загалом інтерфейс може мати лише загальнодоступних членів, оскільки єдина функція інтерфейсу має передаватися у спадок.

З підручника PHPfreaks.com:

PHP5 має інтерфейси. Щоб не плутати з інтерфейсами в більш загальному розумінні, ключове слово interface створює сутність, яка може бути використана для накладання загального інтерфейсу на класи, не розширюючи їх, як з абстрактними класами. Натомість реалізований інтерфейс.

Інтерфейси відрізняються від абстрактних класів. По-перше, вони насправді не є класами. Вони не визначають властивостей і не визначають жодної поведінки. Методи, заявлені в інтерфейсі, повинні бути оголошені в класах, які його реалізують.

Оскільки інтерфейс у більш загальному розумінні є визначенням того, як об'єкт взаємодіє з іншим кодом, усі методи повинні бути оголошені загальнодоступними (див. Розділ про видимість у цій главі). Використовуючи абстрактні класи, абстрактний метод може мати будь-яку видимість, але класи, що розширюються, повинні мати свої реалізації з однаковою (або слабшою) видимістю. Реалізація інтерфейсу додає методи як абстрактні методи до класу предметів, якщо його реалізація призведе до такої помилки:

Фатальна помилка: Клас SomeConcreteClass містить n абстрактних методів (методів) і тому повинен бути оголошений абстрактним або реалізовувати решту методів Так, абстрактні класи можуть реалізовувати інтерфейси.


4
Це дуже погано. Тому що я хотів би мати загальнодоступний метод, необхідний інтерфейсу, реалізований в абстрактному класі, який покладається на захищений метод, який також забезпечується інтерфейсом. Таким чином, абстрактний клас може надати загальнодоступний інтерфейс, але підкласи мають реалізувати основну логіку. Мати сенс?
Stoutie

4
Здається, ви хочете, щоб метод, реалізований підкласом, був абстрактним. Тоді будь-який підклас ПОВИНЕН його реалізувати. Але це не має нічого спільного з інтерфейсом.
Свен

6

інтерфейси - це оголошення типів. тип - це набір значень плюс набір операцій, які можуть бути здійснені над ними ззовні. приватний метод не вписується в цю картину.

interface T {
  public /*int*/ function f(array $a);
}
interface U {
  public /*T*/ function g(T $t);
}

class C implements U {
    public function g(T $t) {
        ...
        $x = $t->f();
        ...
    }
}

інтерфейси корисні, оскільки в них зазначаються, ну, інтерфейси об'єктів. як об’єкти спілкуються із своїм оточенням.

тепер, скажімо, T::fможе бути оголошено приватним. як це було б корисно для інших об’єктів? він не може викликатися ззовні, це не буде частиною його інтерфейсу.


Погоджено ... Але його можна захистити, правда? Як дозволяють абстрактні класи ...
asdfasdfasdf

4

У багатьох випадках визначення інтерфейсу допомагає іншим модулям гарантувати поведінку та API класу. У цих випадках приватні методи - це не те, до чого інші модулі можуть отримати доступ або зрозуміти. Ось чому ви ніколи не можете розміщувати приватні методи на інтерфейсі.


0

Велике НІ , будь-який метод в Інтерфейсі ніколи не матиме приватного або захищеного ідентифікатора доступу.

** Усі методи, заявлені в інтерфейсі, повинні бути загальнодоступними; така природа інтерфейсу.

Кілька інших цікавих фактів про інтерфейс

Інтерфейси можуть бути розширені як класи за допомогою оператора extends. Вони можуть розширювати лише інші інтерфейси. (джерело: https://www.php.net/manual/en/language.oop5.interfaces.php )

Зверніть увагу, що можна оголосити конструктор в інтерфейсі, що може бути корисним у деяких контекстах, наприклад для використання фабриками. Підпис повинен бути однаковим у класі дитини.

У вашому випадку навіть інша проблема полягає в тому, що в оголошенні функції відсутнє ключове слово function. Вона повинна бути

interface iService
{
    public function method1();
}

0

Як зазначалося, інтерфейси можуть визначати лише загальнодоступні методи. Я хотів показати приклад того, як можна обробляти захищені методи. Щоб нав'язати використання конкретних захищених методів, можна створити абстрактний клас, який реалізує інтерфейс.

Це особливо має сенс, якщо абстрактний клас вже може обробляти частину робочого навантаження, щоб спростити фактичну реалізацію. Ось, наприклад, абстрактний клас дбає про створення об'єкта результату, який завжди необхідний:

По-перше, інтерфейс.

interface iService
{
   /**
    * The method expects an instance of ServiceResult to be returned.
    * @return ServiceResult
    */
    public function doSomething();
}

Потім абстрактний клас визначає внутрішню структуру методів:

abstract class AbstractService implements iService
{
    public function doSomething()
    {
        // prepare the result instance, so extending classes
        // do not have to do it manually themselves.
        $result = new ServiceResult();

        $this->process($result);

        return $result;
    }

   /**
    * Force all classes that extend this to implement
    * this method.
    *
    * @param ServiceResult $result
    */
    abstract protected function process($result);
}

Клас, який виконує фактичну реалізацію, автоматично успадковує інтерфейс від абстрактного класу і потребує лише реалізації захищеного методу.

class ExampleService extends AbstractService
{
    protected function process($result)
    {
         $result->setSuccess('All done');
    }
}

Таким чином інтерфейс виконує державний контракт, а через AbstractServiceклас виконується внутрішній контракт. Програмі потрібно лише забезпечити використання AbstractServiceкласу там, де це можливо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.