Какова цель интерфейсов в php? - PullRequest
8 голосов
/ 07 декабря 2010

Если я определяю интерфейс в PHP и фабричный класс, который создает экземпляр этого интерфейса, могу ли я заставить клиентский код использовать только интерфейс, а не базовый конкретный класс?Насколько я понимаю, клиенты могут использовать любые открытые функции / поля в базовом классе.

Вот пример:

<?php
interface IMyInterface
{
    public function doSomething();
}
?>

<?php
class ConcreteImplOfMyInterface implements IMyInterface
{
    const NotPartOfInterface = 'youcantseeme';

    public function doSomething()
    {
    }
}
?>

<?php
class MyInterfaceFactory
{
    public static function createMyInterface()
    {
        return new ConcreteImplOfMyInterface(); 
    }
}
?>

<?php
function client()
{
    $myInterface = MyInterfaceFactory::createMyInterface();
    return $myInterface::NotPartOfInterface;
}
?>

Ответы [ 4 ]

9 голосов
/ 07 декабря 2010

Вот почему интерфейсы хороши в PHP:

interface Printable{
    public function display();
}

function display(Printable $obj){
    $obj->display();
}

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

PHP 5.1 http://php.net/manual/en/language.oop5.typehinting.php

Если вы хотите убедиться, что кто-то другой не может использоватьконкретные методы или переменные класса, вы должны определить эти методы и переменные как private.Это сделает их неспособными использоваться чем-либо, кроме этого определенного класса.(Даже классы, расширяющие ваш класс, не могут их использовать)

6 голосов
/ 07 декабря 2010

То, что вы просите, возможно только для статически типизированного языка, а поскольку PHP динамически типизирован, короткий ответ заключается в том, что это невозможно.

Например, в Java createMyInterface можетвернуть IMyInterface, и единственными возможными операциями над этим объектом являются те, которые определены в самом интерфейсе.Конечно, объект действительно имеет тип ConcreteImplOfMyInterface, поэтому вы всегда можете привести его к этому типу для доступа к другим полям / методам.

PHP не имеет объявленных типов, поэтому вы возвращаете из функции следующее:просто «переменная» - она ​​не имеет типа.И поскольку типов нет, все поиски полей / методов являются динамическими, поэтому всегда можно получить доступ ко всему, что «есть» в объекте.

В некотором смысле, интерфейсы действительно несколько ограничены в использовании в языкенапример, PHP - любой класс, который реализует интерфейс, должен реализовывать все его методы, но, поскольку нет никакой гарантии относительно того, что функция может возвратить в первую очередь, по сути, вообще нет никакой гарантии.Лучшее, что вы можете сделать, это использовать instanceof, чтобы проверить, реализует ли неизвестная переменная данный интерфейс.

2 голосов
/ 07 декабря 2010

Поскольку PHP является динамическим языком, это означает, что все обращения к членам класса и т. Д. Будут разрешены во время выполнения. Это означает, что если у меня есть код, который вызывает $ foo-> bar (), и я получил объект в $ foo, у которого есть метод bar (), то он будет вызван, даже если это не тот метод bar (), который я намеревался вызвать но какой-то другой метод на каком-то другом объекте, который по совпадению назван так же.

Однако, как говорится, вы можете обеспечить некоторую защиту, используя набранные параметры, чтобы функция принимала только определенные объекты:

function doingSomething(IMyInterface $foo) {
  $foo->doSomething();
}

Однако вы все равно не можете запретить кому-либо реализовывать IMyInterface и затем писать функции, которые принимают IMyInterface, но используют его так, как если бы он был объектом некоторого более высокого класса. Как я уже сказал, это связано с тем, что PHP является динамическим языком.

1 голос
/ 07 декабря 2010

Сделайте методы приватными.

return $myInterface.NotPartOfInterface;

Это работает? Я не думаю, что это должно. Я думаю, вам нужен оператор ::.

. используется только для объединения строк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...