Что такое определение «интерфейс» в объектно-ориентированном программировании - PullRequest
95 голосов
/ 19 мая 2010

Хорошо, мой друг говорит о том, что означает "интерфейс" в программировании.

Каково лучшее описание «интерфейса».

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

Ответы [ 16 ]

155 голосов
/ 19 мая 2010

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

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

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

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

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

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

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

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

148 голосов
/ 09 января 2013

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

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

У вас нет оружия.

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

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

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

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

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

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

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

Подводя итог:

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

34 голосов
/ 19 мая 2010

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

16 голосов
/ 19 мая 2010

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

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

7 голосов
/ 19 мая 2010

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

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

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

5 голосов
/ 11 апреля 2013

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

Рассмотрим этот фрагмент кода 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. Игру сейчас называют двумя разными объектами, каждый из которых реализует правильный интерфейс. Другие классы выдают ошибку при сборке кода.

Здесь я заметил аналогию с планом:

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

Это все из-за статически типизированной природы некоторых языков OO, как в случае с 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 (), все в порядке. Если это не так: KAPUTT! Эта ошибка будет видна не во время компиляции, а во время выполнения, поэтому, возможно, когда ваша программа уже развернута и работает. 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, поскольку Java не может перемешиваться с функциями, как это могут другие два (Python и C #). Там интерфейсы - ваш единственный способ описать поведение таким образом в av.

4 голосов
/ 19 мая 2010

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

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

2 голосов
/ 25 января 2013

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

2 голосов
/ 19 мая 2010

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

1 голос
/ 25 августа 2014

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

Определение интерфейса со временем изменилось. Как вы думаете, интерфейс имеет только объявления методов? Как насчет статических конечных переменных и определений по умолчанию после 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

...