Модификаторы доступа в интерфейсах

CRL

Новичок
Модификаторы доступа в интерфейсах

Аналогичные темы уже поднимались, и неоднократно, однако, читая их я так и не смог прояснить ситуацию относительно модификаторов доступа в интерфейсах. Я понимаю, что методы интерфейса не могут быть private, иначе их нельзя будет реализовать, но я не понимаю, почему они не могут быть protected.
Имеется интерфейс:
PHP:
interface ICatalogue
    {
       protected function showCat();
    }
Он реализуется классом:
PHP:
class Lib implements ICatalogue
    {
                
        protected function showCat()
        {
            print "test";
        }
        
    }
Возникает ошибка: Fatal error: Access type for interface method ICatalogue::showCat() must be omitted

Мануалы на php.net и на данном сайте, рассказывая об интерфейсах, как-то обходят стороной этот вопрос, а у Котерова и Костарева в "РНР5 в подлиннике" относительно интерфейсов сказано: "...интерфейс указывает лишь список методов, их аргументы и модификаторы доступа (обычно только protected и public). Допускается так же описание констант внутри интерфейса." Вопрос возник в связи с тем, что если модификатор доступа в интерфейсе public, то, соответственно, в реализации я не могу сделать его строже, а если не public, то возникает упомянутая ошибка. Как быть?
 

zerkms

TDD infected
Команда форума
Мануалы на php.net и на данном сайте, рассказывая об интерфейсах, как-то обходят стороной этот вопрос
нисколько, на то он и интерфейс, чтобы описывать публичные методы :)
http://ru2.php.net/interface
All methods declared in an interface must be public, this is the nature of an interface.
в твоём случае, дабы гарантировать наличие метода у объекта, используй абстрактный класс
 

berkut

Новичок
дык интерфейс-то по идее на то и называется интерфейсом, шоб там всё только паблик было. чё-то ты значит не то творишь
 

CRL

Новичок
Автор оригинала: Андрейка
CRL
а interface зачем собстно нужен?
Насколько я понимаю смысл интерфейсов, они - ничего не реализуя - являются каталогизаторами описаний для последующей реализации. В моем случая, делая библиотечный каталог, я хочу разделить описания разнозадачных функций (идентификация пользователя в библиотеке и настройка его профиля, работа с библиотечным каталогом), разместив их в разных интерфейсах, а для реализации создать один класс, имплементирующий оба интерфейса, и при этом мне бы не хотелось, чтобы явно служебные функции, навроде коннекта с базой, размещались в публичной области.
 

Wicked

Новичок
неправильно понимаешь.
http://ru.wikipedia.org/wiki/Интерфейс_(объектно-ориентированное_программирование):
Интерфейс определяет границу взаимодействия между классами или компонентами, специфицируя определенную абстракцию, которую осуществляет реализующая сторона.
ни про какие приватные/защищенные методы не может быть и речи.
 

CRL

Новичок
Автор оригинала: berkut
дык интерфейс-то по идее на то и называется интерфейсом, шоб там всё только паблик было
Вот этот момент мне совершенно непонятен. Вопрос в том, для кого "всё только паблик было"? Интерфейс не может использоваться самостоятельно и должен быть реализован, соответственно, мне кажется очень странным, что интерфейс накладывает такие ограничения на модификаторы доступа для реализующих его классов - получается, что интерфейс просто принуждает реализующие его классы быть public даже тогда, когда это совсем не нужно.
 

rotoZOOM

ACM maniac
Интерфейсы служат, чтобы отделить конкретные реализации объектов от выполняемого ими функционала.
Допустим у тебя есть класс A, который знает, что существует такой интерфейс IA, который реализует определенный функционал, который необходим A. Классу А абсолютно плевать, какой именно класс реализует данный интерфейс, и он даже не знает название этого класса. Он просто пользуется объектом этого класса, используя интерфейс IA.
Таким образом, чтобы классу A юзать класс IDONTKNOW, который реализует интерфейс IA, необходимо, чтобы методы в IA были паблик.
В этом суть интерфейса.
А то, что тебе надо, это как уже сказали используй просто абстрактный класс.
 

rotoZOOM

ACM maniac
Сразу предупреждаю, не проверял.
Только суть.
PHP:
/**
* Сам интерфейс
*/
interface IInput
{
    public function getMessage ();
}

/**
* Класс, реализующий интерфейс
*/
class RS232 implements IInput
{
    public function getMessage ()
    {
         // == get Message from COM-port
         ...
         return $msg;
    }
}

....
class DataProvider
{
    /**
    * Вот тут $io - является объектом класса
    * который реализцет интерфейс IInput
    * а классу DataProvider глубоко плевать какой
    * именно это класс на самом деле
    */
    public function __construct($io)
    {
          $this->iio=$io;
    }

    /**
    * какой-то метод
    */
    public function Do()
    {
          $m=$this->iio->getMessage();
    }

     private  $iio;
}

...
// == где нибудь высоко в горах
$ino=new RS232();
$dp=new DataProvider ($ino);
$dp->Do();
Таким образом класс DataProvider не знает, что на свете существует класс RS232, но он знает, что тот объедк,
который ему передают в конструкторе реализует интерфейс
IInput (ну точнее может это проверить).
 

Wicked

Новичок
rotoZOOM
желательно еще проверять, что $io действительно имплементирует сей интерфейс:
PHP:
public function __construct($io)
{
  if(!($io instanceof IInput)) {
    throw new ArgumentException()
  }
  $this->iio=$io;
}
 

Wicked

Новичок
StUV
а по мне так эксепшены несколько лучше, чем fatal error'ы.
 

itprog

Cruftsman
ну не совсем фатал, а catchable fatal, их легко "поймать" через свой error_handler
 

StUV

Rotaredom
а по мне так эксепшены несколько лучше, чем fatal error'ы
хм
ексепшны уровня нарушения интерфейсов ?..
по-моему, это просто нерабочий код - т.е. ошибка уровня "до тестирования" - не то чтобы продакшна

а ексепшны - они для ошибок логики приложения, но никак не семантики
 

berkut

Новичок
public function __construct(IInput $io)
просто красивее)
и читается легче - сразу всё ясно. и автокомплит в редакторах его показывает
 
Сверху