Интерфейс (объектно-ориентированное программирование). Интерфейсы vs. классы

Для Андроид 16.06.2019

) - это семантическая и синтаксическая конструкция в коде программы, используемая для услуг, предоставляемых или .

Интерфейсы в Delphi

Интерфейсы в C++

Роль интерфайсов в C++ выполняют абстрактные классы.

Интерфейсы в Java

Объявление интерфейсов

Объявление интерфейсов очень похоже на упрощенное объявление классов.

Оно начинается с заголовка. Сначала указываются модификаторы. Интерфейс может быть объявлен как public и тогда он будет доступен для общего использования, либо модификатор доступа может не указываться, в этом случае интерфейс доступен только для своего пакета. Модификатор abstract для интерфейса не требуется, поскольку все интерфейсы являются . Его можно указать, но делать этого не рекомендуется, чтобы не загромождать .

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

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

Затем в фигурных скобках записывается интерфейса.

Public interface Drawble extends Colorable, Resizable { }

Тело интерфейса состоит из объявления , то есть - и абстрактных методов. Все поля интерфейса должны быть public final static , так что эти модификаторы указывать необязательно и даже нежелательно, чтобы не загромождать . Поскольку поля объявляются , необходимо их сразу инициализировать.

Public interface Directions { int RIGHT=1; int LEFT=2; int UP=3; int DOWN=4; }

Все методы интерфейса являются public abstract и эти модификаторы также необязательны.

Public interface Moveable { void moveRight(); void moveLeft(); void moveUp(); void moveDown(); }

Как мы видим, описание интерфейса гораздо проще, чем объявление класса.

Реализация интерфейса

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

В процессе поиска новой работы столкнулся с тем, что все работодатели хотят, чтобы было отличное знание ООП в ПХП. Чем я хуже других, подумал я, и решил перечитать главу про объектно-ориентированное программирование. И вот на очередном собеседовании мне задают вопрос — чем абстрактный класс отличается от интерфейса.
Единственное отличие, которое я знал было в том, что один класс может реализовать несколько различных интерфейсов. Но обо всем по порядку.

Абстрактные классы
Абстрактные классы используются в PHP для определения абстрактных объектов. Чтобы понять, что определяет абстрактный объект, давайте рассмотрим такое понятие, как “пища”. Все мы знаем, что такое “пища”, но не всегда смотрим на то, из чего конкретно она приготовлена. Вы видели самые разнообразные виды пищи (бифштексы, цыпленок и тому подобное), однако само по себе понятие пищи является абстрактным - оно существует только как обобщение более конкретных вещей. Подобная идея справедлива также и для абстрактных классов.

В ООП абстрактные классы предназначены для того, чтобы создать суперкласс, который будет определять абстрактные характеристики его классов-наследников. На самом деле абстрактные классы могут содержать в себе какой-либо код, а могут быть вообще без кода; кроме этого, на их основе нельзя создать экземпляр напрямую. Рассмотрим пример:

value = NULL; } } class Integer extends Number { private $value; public function value() { return (int)$this->value; } } $num = new Integer; /* Все в порядке */ $num2 = new Number; /* Возникнет ошибка */ ?>

abstract class Number {

private $value ;

abstract public function value () ;

public function reset () {

$this -> value = NULL ;

class Integer extends Number {

private $value ;

public function value () {

return (int ) $this -> value ;

$num = new Integer ; /* Все в порядке */

$num2 = new Number ; /* Возникнет ошибка */

Тут мы создали абстрактный класс Number, который является расширением класса Integer. Поскольку класс Number объявлен как abstract, на его основе нельзя создавать экземпляры. Если посмотреть на класс Number, то можно увидеть, что в нем определены две функции: value() и reset(). Абстрактный класс может не содержать код для методов, хотя при необходимости его можно добавить. Что же касается класса Number, то поскольку функция value() является специфической для конкретного типа числа, она реализуется в классе-наследнике. Чтобы разработчик мог реализовать такое поведение в своем коде, используется ключевое слово abstract, указывающее на то, что это просто заполнитель в классе Number. Однако это не относится к методу reset(), который остается неизменным для любого конкретного типа числа.

Интерфейсы
В отличие от абстрактных классов, посредством которых можно выражать абстрактные понятия в программах, интерфейсы предназначены для того, чтобы обеспечить определенную функциональность внутри класса. Если выражаться точнее, то интерфейс представляет собой средство для определения набора методов, которые должен иметь класс, реализующий данный интерфейс. Чтобы использовать интерфейс, его необходимо объявить с указанием ключевого слова interface:

interface printable {

public function printme () ;

Чтобы интерфейс приносил определенную пользу, он должен быть реализован с помощью одного или нескольких классов. Далее будет определен интерфейс printable, который заявляет, что любой класс, реализующий этот интерфейс, должен реализовать метод printme(). Чтобы создать класс, реализующий подобный интерфейс, в определении класса используется ключевое слово implements, за которым следует список реализованных интерфейсов:

value; } public function printme() { echo (int)$this->value; } } ?>

class Integer implements printable {

echo (int ) $this -> value ;

Здесь определен исходный класс Integer, чтобы реализовать интерфейс printable. Как класс, реализующий этот интерфейс, он гарантирует, что класс Integer предложит все методы, которые определены в интерфейсе.

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

P.S. — Большая часть статьи — не моя, а взята из книги, где, на мой взгляд, наиболее понятно описана разница между абстрактными классами и интерфейсами.
P.P.S. — Так же, не особо понятно зачем вообще нужно ООП в PHP, т.к. прям явных преимуществ я не вижу, а все это можно реализовать с помощью простых функций… Единственный раз, когда я за свою жизнь использовал ООП — это для реализации класса, работающего с базами данных.

В PHP ООП интерфейс — это класс, в котором все методы являются абстрактными и открытыми.

Быстро пробежимся по трем терминам, используемым в этом определении. Класс, абстрактный и открытый. Класс представляет собой шаблон или образец объекта, он является основой объектно-ориентированного программирования. Абстрактный — это специальный метод, который объявляется, но не имеет тела, только пустые скобки. Открытый — это модификатор доступа public , он связан с доступом к методам. Это означает, что он доступен из любого места: из этого класса, вне его пределов и из любого производного класса.

Интерфейс PHP представляет собой инструмент для создания надежного кода, определяющего методы, которые должны быть реализованы с помощью класса без определения обработки этих методов. Это мощная и простая концепция, используемая в объектно-ориентированном PHP . Для его создания используется ключевое слово interface , он определяется так же, как класс PHP . Методы, содержащиеся в нем, не имеют никакого функционала, но интерфейс задает, какие методы необходимы для других классов. Любой класс, наследующийся от интерфейса, должен содержать те же методы, которые содержатся в интерфейсе, иначе выдается ошибка.

В интерфейсе ООП PHP мы задаем только имена методов и их параметры, а реализованы они могут быть позже. Принято объявлять все методы интерфейса как public . Для реализации интерфейса используется ключевое слово implements . При необходимости класс может реализовать более одного интерфейса, между собой они разделяются запятой. Как и класс, интерфейс может содержать константы. Единственное отличие заключается в том, что они не могут быть переопределены в производном классе.

Определение и использование интерфейсов

Интерфейс определяется с помощью ключевого слова interface . Все методы в нем должны быть открытыми и абстрактными:

interface animal { }

Это пустой интерфейс. Мы добавим в него абстрактный метод motion . Таким образом, мы создадим простой PHP 5 ООП интерфейс, который может быть реализован позже:

interface animal { public function motion(){} }

Этот интерфейс может быть реализован любым классом animal , все классы animal будут содержать метод motion . Давайте рассмотрим пример. Для реализации интерфейса мы используем ключевое слово implements :

PHP-интерфейс и абстрактные классы

Интерфейсы и абстрактные классы очень похожи по своей концепции. Они помогают в создании шаблонов для классов, которые будут использоваться в приложении. Согласно основам ООП PHP , они отличаются друг от друга следующим:

  1. В интерфейсе все методы являются абстрактными (без реализации ). В абстрактном классе лишь некоторые методы являются абстрактными. Абстрактный класс должен содержать, по крайней мере, один абстрактный метод. Иначе это будет стандартный класс PHP ;
  2. В интерфейсе PHP все объявленные методы являются открытыми, а в абстрактном классе методы могут быть открытыми, частными или защищенными. Следовательно, для интерфейсов существует ограничение на использование модификаторов доступа, а в абстрактном классе таких ограничений нет;
  3. Класс может реализовать неограниченное количество интерфейсов. В то же время класс PHP может породить только один абстрактный класс;
  4. Вы должны переопределять все методы интерфейса, а в абстрактном классе у вас есть выбор: переопределять методы или оставить их без изменений;
  5. Интерфейсы имеют более строгие правила, чем абстрактные классы. Интерфейс PHP призван обеспечить определенную логику, он выступает в качестве пустой оболочки или шаблона для других классов.

Для чего используются интерфейсы PHP

Интерфейс помогает программисту мыслить в правильном направлении. С точки зрения PHP ООП , класс представляет собой шаблон, а объект — это набор возможностей. Мы в большей степени связаны с функционалом, что он делает, а не как он это делает. Поэтому мы определяем основной интерфейс, который является общим, а затем он реализуется, что помогает мыслить в правильном направлении.

Корректировка кода в будущем

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

Лучшая структура программы

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

Добавление всех важных функций

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

Еще один в ООП PHP пример реализации интерфейса

class Cake implements Recipe { public function methodology() { } }

В этом коде мы видим класс Cake , который реализует интерфейс Recipe .

Перевод статьи «PHP interface » был подготовлен дружной командой проекта .

Интерфейс (иногда так же контракт , interface ) в объектно-ориентированной парадигме программирования - частный случай абстрактного класса.

Общее понятие интерфейса и сравнение с абстрактным классом

В отличие от абстрактного класса, который может содержать в себе почти всё то же, что и обычный класса, интерфейс может содержать в себе только константы и абстрактные методы. Все элементы интерфейса являются публичными (public) так как это заложено самой природой интерфейса, поэтому модификатор доступа к элементам интерфейса можно и не писать, там по умолчанию всё public . В Java в интерфейсах можно декларировать и обычные переменные, что может запутать так как компилятор хоть и разрешает это делать, но всё равно все переменные интерфейса превращаются в константы.

Предназначение интерфейсов

Интерфейсы нужны для стандартизации взаимодействий объектов. Интерфейсы не предназначены для хранения данных, они определяют именно общие принципы взаимодействия с классами реализовывающие их.

Интерфейсы выполняют всё ту же роль абстрактных элементов, то есть заставляют реализующие классы реализовывать описанные абстрактные методы. По этому интерфейсы реализовывают (не расширяют/наследуют), а именно реализовывают в классах. Разумеется, создать объект интерфейса нельзя. Использовать напрямую абстрактные классы и интерфейсы нельзя, их надо расширять/наследовать и реализовывать.

Основные моменты касательно интерфейсов

Интерфейсы могут наследоваться только друг от друга и даже множественно. При этом обычно наследование одного интерфейса от другого, как и в случае наследования классов, именуется расширением, ключевое слово extends .

В отличие от классов интерфейсы не расширяют или наследуют а реализуют (ключевое слово implements). Так же большинстве языков программирования разрешено множественное наследование интерфейсов в отличие от классов, которые можно наследовать только по одному.

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

Языки использующие интерфейсы

Интерфейсы присущи современным ленивым объектно-ориентированным языкам программирования таким как Java и C#. В том же хардкорном C++ интерфейсов нет так как там для этого есть абстрактные классы и разрешённое множественное наследование классов.

Правила хорошего тона написания программного кода и интерфейсы

По правилам хорошего тона написания программного кода первая буква названия интерфейса так же как и в названиях классов пишется в верхнем регистре, часто так же добавляют префикс - буква «I», что бы явно можно было отличить интерфейс от класса по названию, хотя часто и к названиям классов добавляют префикс «C» но встречается это реже чем подобная же практика у интерфейсов.

Интерфейсы можут быть и пустыми и при этом всё равно использоваться. В этом случае они являются некими маркерами позволяющими группировать классы по каким-нибудь категориям. Поэтому наследование пустых интерфейсов это частая практика.

Интерфейс и абстрактный класс

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

Примеры интерфейсов

PHP

Пример описания интерфейса на PHP:

interface IHand { function useKeyboard(); function touchNose(); } interface IFoot { function runFast(); function playFootball(); } class Human implements Hand, Foot { function useKeyboard() {echo "Use keyboard!"}; function touchNose() {echo "Touch nose!"}; function runFast() {echo "Run fast!"}; function playFootball() {echo "Play football!"}; }

Для начала нужно сразу понять, что интерфейс это частный случай класса. Но в Java оно имеет отдельное ключевое слово, а в C++ это просто класс без реализации. Поэтому интерфейс просто задает некий стандарт для работы с кучей разнообразных реализаций.

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

А если вы делаете игру, то можете создать интерфейс Unit, тем самым задав классам определенное поведение. Например, unit должен обязательно иметь метод atack(), isDead() и т.д.

Ну и конечно Unit может быть и просто классом или абстрактным классом, в котором реализованы atack и isDead, а может быть только isDead, потому что attack у каждого типа юнита индивидуально и требует собственной реализации. Т.е. приходим к тому, что интерфейс это также частный случай абстрактного класса.

Т.е. тут уже вступает в действие полиформизм, т.е. интерфейсы по сути дают полиформизм. Ну, а в Java они еще позволяют делать множественное наследование или другими словами задать классу несколько свойств поведения, например Unit может быть также и Iterable, тем самым можно дать юнитам инвентарь и перебирать элементы в нем.

И соответсвенно если Unit у вас будет классом или абстрактным классом, то унаследовав Unit в Java, вы просто не сможете дать наследнику еще и Iterable поведение, если Iterable будет тоже классом.

OrcWarrior implements Unit, Iterable - так можно

OrcWarrior extends Unit, Iterable - так в Java нельзя, но можно в С++, а Unit и Iterable тогда всегда будут объявляться как class...

Из-за этого, в Java приветствуется не наследование, а композиция. Т.е. нафига каждый раз реализовывать Unit.isDead, если он стандартный? Поэтому, создается скажем класс UnitAI и делается следующее:

Class OrcWarrior implements Unit, Iterable {
UnitAI ai;

UnitAI getAI(){
return ai;
}
}

Boolean isDead() {
....
}
}

Interface Unit {
void attack();
UnitAI getAI();
}

Вот это называется композиция, т.е. в OrcWarrior, HumanWarrior вы подмешиваете UnitAI, в котором уже реализовано isDead, и тем самым не нужно каждый раз его реализовывать одним и тем же кодом. В С++ такого можно не делать, там есть поддержка множественного наследование, но оно имеет свои минусы. Впрочем, как и композиция имеет плюсы/минусы.



Рекомендуем почитать

Наверх