Что такое определение «интерфейса» в объектно-ориентированном программировании?

108

Хорошо, мой друг обсуждает, что такое «интерфейс» в программировании.

Как лучше всего описать "интерфейс".

Для меня интерфейс - это план класса, это лучшее определение?

Даниэль Киватинос
источник
1
не обман, но он проливает свет на этот вопрос: stackoverflow.com/questions/444245/…
rmeador
Я бы сказал, что это общее слово, но для меня все равно означает то же самое. Это похоже на стену для определенного или более абстрактного объекта, предоставляющего некоторые входные точки наружу и выдающего им выходные данные без каких-либо знаний о внутренних операциях. Я думаю, это можно назвать абстракцией для определения классов от более низкого до более высокого уровня в ООП.
Икбал

Ответы:

180

Интерфейс - один из наиболее перегруженных и запутанных терминов в разработке.

На самом деле это концепция абстракции и инкапсуляции. Для данного «бокса» он объявляет «входы» и «выходы» этого бокса. В мире программного обеспечения это обычно означает операции, которые могут быть вызваны в поле (вместе с аргументами), а в некоторых случаях - типы возвращаемых данных этих операций.

Чего он не делает, так это определения семантики этих операций, хотя обычным явлением (и очень хорошей практикой) является их документирование рядом с объявлением (например, посредством комментариев) или выбор хороших соглашений об именах. Тем не менее, нет никаких гарантий, что эти намерения будут реализованы.

Вот аналогия: посмотрите на свой телевизор, когда он выключен. Его интерфейс - это кнопки, различные разъемы и экран. Его семантика и поведение таковы, что он принимает входные данные (например, кабельное программирование) и имеет выходы (отображение на экране, звук и т. Д.). Однако, когда вы смотрите на телевизор, который не подключен к розетке, вы проецируете ожидаемую семантику в интерфейс. Насколько вам известно, телевизор может просто взорваться, когда вы его включите. Однако, исходя из его «интерфейса», вы можете предположить, что он не будет готовить кофе, поскольку в нем нет воды.

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

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

В других языках, таких как C ++, у вас нет интерфейсов. Сам класс определяет методы, но вы можете думать об интерфейсе класса как об объявлениях не частных методов. Из-за того, как C ++ компилируется, вы получаете файлы заголовков, где у вас может быть «интерфейс» класса без фактической реализации. Вы также можете имитировать интерфейсы Java с абстрактными классами с чистыми виртуальными функциями и т. Д.

Интерфейс определенно не является планом класса. План по одному определению - это «подробный план действий». Интерфейс ничего не обещает о действии! Источник путаницы заключается в том, что на большинстве языков, если у вас есть тип интерфейса, который определяет набор методов, класс, который его реализует, «повторяет» те же методы (но предоставляет определение), поэтому интерфейс выглядит как скелет или план класса.

Ури
источник
Я читаю книгу по Objective-C, и мне кажется, что авторы используют термины «протокол» и «интерфейс» как синонимы. Правильно ли говорить, что «протокол» и «интерфейс» - это одно и то же, или мне что-то не хватает?
Fazzolini
1
Я бы не стал использовать слово «протокол» для «интерфейса». Слово «протокол» подразумевает уровень детализации того, как выполняются действия. «Интерфейс» действительно отличное слово с чисто английским определением, которое точно описывает, что это такое.
OCDev
В Windows интерфейсы программирования используются довольно широко, поэтому даже в C ++ вы можете встретить «интерфейсы» в виде объектов, которые не связаны с реализацией.
Victoria
167

Рассмотрим следующую ситуацию:

Вы находитесь в центре большой пустой комнаты, когда на вас внезапно нападает зомби.

У тебя нет оружия.

К счастью, в дверях комнаты стоит еще один живой человек.

"Быстрый!" вы кричите на него. «Брось мне что-нибудь, чем я могу ударить зомби!»

А теперь подумайте:
вы не указали (и вас это не волнует), что именно ваш друг выберет, чтобы выбросить;
... Но это не имеет значения, если:

  • Это то, что можно выбросить (он не может бросить вам диван)

  • Это то, за что можно ухватиться (будем надеяться, что он не бросил сюрикен)

  • Это то, что вы можете использовать, чтобы разбить зомби мозги (это исключает подушки и тому подобное)

Неважно, достанете ли вы бейсбольную биту или молоток -
пока она выполняет три ваших условия, все в порядке.

Подвести итог:

Когда вы пишете интерфейс, вы в основном говорите: «Мне нужно что-то, что ...»

Иегуда Шапира
источник
13
Собственно, подушка все равно подойдет. Вы можете поразить им зомби. Вышибите зомби мозги ... ну, это вопрос производительности, которая никогда не является частью интерфейса.
meustrus
35

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

Евгений Кулешов
источник
1
На самом деле мне не нравится здесь неквалифицированный срочный контракт, потому что контракт часто подразумевает семантику или поведение (как при проектировании по контракту). Не все интерфейсы подразумевают какую-либо семантику или поведение. Например, «дыра в стене» - это интерфейс реального мира. Воспринимаете ли вы это как окно, мусоропровод или что-то еще, это ваша интерпретация.
Ури
3
Правда. Интерфейс - это «контракт подписи метода», то есть он гарантирует реализацию данных методов. Он не дает никаких гарантий относительно того, будет ли это сделано каким-либо образом.
Эрик Функенбуш
Собственно, вам следует дать больше объяснений этому определению. Но интерфейс - это договор между двумя частями. Код по контракту .... +1
matiasnj
18

Я не думаю, что слово «план» - хорошее слово. План подсказывает, как что-то построить. Интерфейс специально не говорит вам, как что-то построить.

Интерфейс определяет, как вы можете взаимодействовать с классом, то есть какие методы он поддерживает.

Дэйв Коста
источник
1
Я считаю, что отправитель запроса спросил, что такое определение, а не то, что это не так. :)
Евгений Кулешов
7

Для меня интерфейс - это план класса, это лучшее определение?

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

Интерфейс состоит из сигнатур методов и значений констант, а также (обычно неформального) «поведенческого контракта» между классами, реализующими интерфейс, и другими, которые его используют.

Стивен С
источник
6

В программировании интерфейс определяет, какое поведение будет иметь объект, но на самом деле он не определяет это поведение. Это контракт, который гарантирует, что определенный класс может что-то сделать.

Рассмотрим этот фрагмент кода C # здесь:

using System;

public interface IGenerate
{
    int Generate();
}

// Dependencies
public class KnownNumber : IGenerate
{
    public int Generate() 
    {
        return 5;
    }   
}

public class SecretNumber : IGenerate
{
    public int Generate()
    {
        return new Random().Next(0, 10);
    }
}

// What you care about
class Game
{
    public Game(IGenerate generator) 
    {
        Console.WriteLine(generator.Generate())
    }
}

new Game(new SecretNumber());
new Game(new KnownNumber());

Классу Game требуется секретный номер. Ради тестирования вы хотели бы ввести то, что будет использоваться в качестве секретного числа (этот принцип называется инверсией управления).

Класс игры хочет быть «непредубежденным» относительно того, что на самом деле создаст случайное число, поэтому он будет запрашивать в своем конструкторе «все, что имеет метод Generate».

Во-первых, интерфейс указывает, какие операции будет выполнять объект. Он просто содержит то, как это выглядит, но фактической реализации не дается. Это просто сигнатура метода. Обычно в C # интерфейсы имеют префикс I. Классы теперь реализуют интерфейс IGenerate. Это означает, что компилятор убедится, что у них обоих есть метод, который возвращает int и вызывается Generate. В игре сейчас называются два разных объекта, каждый из которых реализует правильный интерфейс. Другие классы при построении кода выдали бы ошибку.

Здесь я заметил аналогию с планом, которую вы использовали:

Класс обычно рассматривается как образец объекта. Интерфейс определяет то, что класс должен будет делать, поэтому можно утверждать, что это действительно просто план для класса, но поскольку классу не обязательно нужен интерфейс, я бы сказал, что эта метафора ломается. Думайте об интерфейсе как о контракте. Класс, который его «подписывает», будет юридически обязан (соблюдается полицией компилятора) соблюдать условия контракта. Это значит, что он должен будет делать то, что указано в интерфейсе.

Все это связано со статической типизацией некоторых объектно-ориентированных языков, как в случае с Java или C #. В Python, с другой стороны, используется другой механизм:

import random

# Dependencies
class KnownNumber(object):
    def generate(self):
        return 5

class SecretNumber(object):
    def generate(self):
        return random.randint(0,10)

# What you care about
class SecretGame(object):
    def __init__(self, number_generator):
        number = number_generator.generate()
        print number

Здесь ни один из классов не реализует интерфейс. Python это не заботит, потому что SecretGameкласс просто попытается вызвать любой переданный объект. Если у объекта ИМЕЕТ метод generate (), все в порядке. Если нет: КАПУТТ! Эта ошибка будет замечена не во время компиляции, а во время выполнения, возможно, когда ваша программа уже развернута и запущена. C # уведомит вас задолго до того, как вы приблизитесь к этому.

Причина использования этого механизма наивно указана, потому что в объектно-ориентированных языках естественно функции не являются гражданами первого класса. Как видите, KnownNumberи SecretNumberсодержат ТОЛЬКО функции для генерации числа. Уроки вообще не нужны. Поэтому в Python их можно было просто выбросить и выбрать функции самостоятельно:

# OO Approach
SecretGame(SecretNumber())
SecretGame(KnownNumber())

# Functional Approach

# Dependencies
class SecretGame(object):
    def __init__(self, generate):
        number =  generate()
        print number

SecretGame(lambda: random.randint(0,10))
SecretGame(lambda: 5)

Лямбда - это просто функция, которая была объявлена ​​«на ходу». Делегат в C # такой же:

class Game
{
    public Game(Func<int> generate) 
    {
        Console.WriteLine(generate())
    }
}    

new Game(() => 5);
new Game(() => new Random().Next(0, 10));

Боковое примечание: последние примеры были невозможны до Java 7. Там интерфейсы были вашим единственным способом указать это поведение. Однако в Java 8 появились лямбда-выражения, поэтому пример C # можно очень легко преобразовать в Java ( Func<int>становится java.util.function.IntSupplierи =>становится ->).

цессор
источник
4

Технически я бы описал интерфейс как набор способов (методов, свойств, средств доступа ... словарь зависит от языка, который вы используете) для взаимодействия с объектом. Если объект поддерживает / реализует интерфейс, вы можете использовать все способы, указанные в интерфейсе, для взаимодействия с этим объектом.

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

Гислен Фурни
источник
2

Лично я вижу интерфейс как шаблон. Если интерфейс содержит определение методов foo () и bar (), то вы знаете, что каждый класс, который использует этот интерфейс, имеет методы foo () и bar ().

Томас Винснес
источник
2

Давайте представим, что Человек (Пользователь или Объект) хочет, чтобы была сделана некоторая работа. Он свяжется с посредником (интерфейс), у которого будет контракт с компаниями (объекты реального мира, созданные с использованием реализованных классов). Он определит несколько видов работ, которые компании будут реализовывать и давать результаты. Каждая компания выполнит работу по-своему, но результат будет одинаковым. Подобно этому Пользователь будет выполнять свою работу с помощью единого интерфейса. Я думаю, что интерфейс будет действовать как видимая часть систем с несколькими командами, которые будут определяться внутренне реализуемыми внутренними подсистемами.

Арун Н
источник
1

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

Люди обычно описывают это как «контракт» на то, что должно быть доступно в методах класса.

Это абсолютно не план, поскольку от него также зависит реализация. Можно сказать, что полное определение класса является планом.

Щенок
источник
1

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

  • убедитесь, что все члены интерфейса реализованы в производном классе (даже если он просто генерирует исключение)
  • Абстрагируйте сам класс от вызывающего (приведите экземпляр класса к интерфейсу и взаимодействуйте с ним без необходимости знать, какой фактический производный класс IS)

для получения дополнительной информации см. http://msdn.microsoft.com/en-us/library/ms173156.aspx

Грег Олмстед
источник
1

На мой взгляд, интерфейс имеет более широкое значение, чем то, что обычно ассоциируется с ним в Java. Я бы определил «интерфейс» как набор доступных операций с некоторыми общими функциями, которые позволяют управлять / контролировать модуль.

В этом определении я пытаюсь охватить как программные интерфейсы, где клиент - это некоторый модуль, так и человеческие интерфейсы (например, графический интерфейс).

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

Эяль Шнайдер
источник
1

Как и выше, уместны синонимы «контракт» и «протокол».

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

Итак, если класс Cheetos Bagреализует Chip Bagинтерфейс, вы должны ожидать, что он Cheetos Bagбудет вести себя точно так же, как и любой другой Chip Bag. (То есть выставить .attemptToOpenWithoutSpillingEverywhere()метод и т. Д.)

Wlangstroth
источник
1

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

Определение интерфейса со временем изменилось. Как вы думаете, в интерфейсе есть только объявления методов? Как насчет статических конечных переменных и как насчет определений по умолчанию после Java 5.

Интерфейсы были введены в Java из-за проблемы Diamond с множественным наследованием, и именно это они и собирались делать.

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

http://www.quora.com/Why-does-Java-allow-static-final-variables-in-interfaces-when-they-are-only-intended-to-be-contracts

Вивек Вермани
источник
0

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

Алиреза Рахмани Халили
источник