Интерфейсы объектов
Читал тут на досуге мануал http://ru2.php.net/manual/ru/language.oop5.interfaces.php и возникли вопросы:
1. зачем оно надо? как это использовать?
2. абстрактный класс и интерфейс. где разница?
Будьте добры, проясните картину... в формате "для чайника"
Разница от абстрактного класса довольно тонкая. Она скорее на уровне понятий класс и интерфейс. Но скажем если абстрактный класс не содержит данных и ни одной реализации методов, только описания - то он практически идентичен интерфейсу. За исключением только возможных проблем при наследовании. Не знаю как в PHP но подозреваю, что наследоваться можно только от одного класса, а вот интерфесов реализовывать сколько угодно.
В С++ например нет в самом языке интерфесов, но есть множественное наследование. Так что там роль интерфейсов как раз исполняют полностью абстрактные классы.
В итоге мы получаем класс, имеющий несколько родителей которые ему не дают ровным счетом НИЧЕГО, кроме ОБЯЗАТЕЛЬСТВА реализовывать их методы! Плюс к этому проблема разрешения имен (если наследуемые интерфейсы будут содержать методы с одинаковыми именами).
В реальной жизне кто-нибудь пользует интерфейсы???
Как раз множественно наследование отчасти и запретили по причине различных реализаций одинаковых методов в родительских классах.
Если мы наследуем интерфейс, то мы ОБЯЗАНЫ реализовать его методы!
В итоге мы получаем класс, имеющий несколько родителей которые ему не дают ровным счетом НИЧЕГО, кроме ОБЯЗАТЕЛЬСТВА реализовывать их методы!
Они дают возможность исспользование полиморфизма во всей его красе.
Еще раз повторяю, в како то месте где нам не важна реализация, мало того, не должно быть зависимости от реализации мы можем смело пользоваться каким то интерфейсом, а в последствии объект класса реализующий этот интерфейс (наравне может с еще несколькими) может быть исспользован в качестве реализации. И нам не надо о нем ничего знать и таких классов может быть множество. Вот пример - представь себе что есть скажем какое то гнездо - например для аудио/видео техники. И устройства подключаемые туда. Нам известен только его интерфейс грубо говоря - форма штекера, форма сигнала идущего через этот штекер и т.п. И все - нам ничего не надо больше знать об устройстве и других его интерфейсах будь это видеомагнитофон, игровая приставка или просто спутниковая антена. Мы просто работаем с нужным интерфейсом в телевизоре и все. Так же и в программе.
В реальной жизне кто-нибудь пользует интерфейсы???
Конечно - это одна из основ ООП, огоромное количество всевозможных паттернов проектирования построенно на исспользовании интерфейсов, да и собственно многие прикладные библиотеки предоставляют пользователю как раз исспользование интерфейсов для работы с ними.
Правильно. Надо же как-то забивать всё увеличивающиеся объёмы оперативной и дисковой памяти. Вот и появляются непродуманные решения, не позволяющие наследовать реализацию, а не только интерфейс.
Ну, гм. Как бы тут помягче? Есть нехорошие дяди, копирующие друг у друга типовые решения. Как водится, зачастую не самые удачные. Им ведь главное, чтобы исходники были открыты... Задумывающимся над смыслом жизни русским приходится страдать, как в поговорке.
Интерфейсы используют там, где они являются частью архитектуры библиотек, например, в Java или .NET. В PHP, как понимаю, прямой необходимости использовать интерфейсы нет.
Что тут сказать? Другие нехорошие дяди, решая проблему непродуманности предыдущих решений, пошли по линии наименьшего сопротивления - решили проблему "милицейским" способом.
В принятой терминологии можно сказать, что ты, aks, продался этим нехорошим дядям и уже не видишь за деревьями леса. Ничего личного.
Если вопросы полезности интерфейсов как способа решения проблемы множественного наследования возникают регулярно у людей с незамутнённым взглядом, всё не так гладко, как пытаются представить "паттерны" использования. Сделанные, кстати, под существующие инструментальные средства, и по западному образцу - "используй, не думая". В поточном программировании без них никак - чем меньше "почему", тем лучше. В обучении же наоборот - чем больше "почему", тем лучше.
Если вопросы полезности интерфейсов как способа решения проблемы множественного наследования возникают регулярно у людей с незамутнённым взглядом, всё не так гладко, как пытаются представить "паттерны" использования.
Они не пытаются представить - они сделанны для удобства и продуктивности разработки.
Хотя думаешь в медленном PHP может и приходиться задумываться о целесобразности исспользуемых парадигм?? )
Абстрактные классы - вещь хорошая. Хоть я ими усиленно ещё и не пользовался, но они позволяют вынести общий цункционал класса.. Т.е. то что статично... Нууу.. Как бы объяснить)) Есть некий объект - он будет разный, ну например круг и квадрат. С ним будут производится одинаковые действия - перемещение по полю(1), изменение цвета(2). Но! Для таких объектов так же будут действия типа изменение размера и т.д. А это уже разная реализация для каждого объекта. Т.е. нам прийдется переписывать 2 объекта в отдельные классы, но при этом в этих классах будут абсолютно 2 одинаковых метода. Что не очень удобно) Поэтому мы создаем абстрактный класс в котором будет (1) и (2) метод, а уже объекты Квадрат и Круг будут расширять этот абстрактный класс
Использую сам и использую постоянно, т.к. не вижу как по другому можно писать на ООП без них (мжет кто и поделится). Я не имею ввиду написание единственного класса, я имею ввиду написание системы.
Есть так же "маркерные" интерфейсы. Марркерные интерфейсы - интрефесы пыстышки, которые нужны для приведению к какому-то типу. Например:
/**
* Используется MVC модель. Данная часть отвечает за M.
*
* Дано. Несколько разных моделей, которые проходят через единую точку.
* Надо. С минимальными изменениями добавить к различным типам комментарии
* PS Моделей много, статьи, новости, блоги и т.д.
* Реализация. Делаем маркерный интерфейс, реализуем его нужными объектами и в этой "единой точке" проверяем
*/
interface Comment_Interface{}
//Далее модели
class Article implements Comment_Interface
{
//Тело
}
class News implements Comment_Interface
{
//Тело
}
class Blog implements Comment_Interface
{
//Тело
}
class Info
{
//Тело
}
//Это та самая, единая точка
class Main
{
public function foo($modelName)
{
$model = new $modelName();
if($model instanceof Comment_Interface) {
//Тут подключаем комментарии
}
}
}
/**
* Теперь для того, чтобы модель могла использовать комментарии, нам нужно всего лишь реализовать маркер.
* На этом основана моя последняя разработка. Плохо это или хорошо, решат вам, но мне удобно
*/
Пример не маркерных интерфейсов:
/**
* Дано. Создать систему логирования. Необходимо предусмотреть прозрачный вывод на несколько типов вывода (файл, экран, письмо и т.д.)
*
*/
class Log
{
/**
* Загружаем драйвер
*
* @param string $driver
* @return Log_Interface
*/
public static function factory($driver, $error)
{
//Опущу все проверки, я для "показать" пишу))
$className = 'Log_' . ucfirst($driver);
$li = new $className($error);
if($li instanceof Log_Interface) {
return $li;
}
throw new Log_Exception('Драйвер долже реализовывать интерфейс Log_Interface');
}
}
class Log_Exception extends Exception{}
interface Log_Interface
{
public function write();
}
class Log_Screen implements Log_Interface
{
private $error;
public function __construct($error)
{
$this->error = $error;
}
public function write()
{
echo $this->error;
}
}
class Log_Email implements Log_Interface
{
private $error;
public function __construct($error)
{
$this->error = $error;
}
public function write()
{
mail('admin@main.com', 'Log message', $this->error);
}
}
//Использование
try {
Log::factory('mail', 'Большая ошибка')->write();
} catch (Log_Exception $e) {
echo $e->getMessage();
}
//Тут мы меняем только имя драйвера и может быть спокойны, что у них у всех есть метод write, кто бы не писал драйвера
в java, опять же, интерфейыс применяются для спецификации некоего стандарта, реализацию которого можно впоследствии заменить другим, реализующим этот же интерфейс (shaelf привёл как раз такой пример с логом)
уместнее всего интерфейсы будут скорее всего там, где применяется некая фабрика объектов.
2aks полностью согласен ;)
в java, опять же, интерфейыс применяются для спецификации некоего стандарта[/QUOTE]
Дык даже не только в Java, а везде. Собственно они не обязывают что то реализовывать, а наоборот - если хочешь соответсвовать некому сандарту (иметь интерфейс ему присущий), реализуй его. ))