Що таке визначення інтерфейсу в об'єктно-орієнтованому програмуванні


108

Гаразд, мій друг, повертайтеся туди, що означає "інтерфейс" у програмуванні.

Який найкращий опис "інтерфейсу".

Для мене інтерфейс - це креслення класу, це найкраще визначення?


1
НЕ боян, але він проливає багато світла на це питання: stackoverflow.com/questions/444245 / ...
rmeador

Я б сказав, що це загальне слово, але все ж означає для мене те саме. Це як стіна для певної або більш абстрактної сутності, яка надає певні вхідні точки зовні і дає їм вихід без будь-яких знань про внутрішні операції. Я думаю, що це можна назвати абстракцією для визначення класів нижчого до вищого рівня в ООП.
ikbal

Відповіді:


179

Інтерфейс - один із найбільш перевантажених та заплутаних термінів у розробці.

Це фактично поняття абстракції та інкапсуляції. Для заданого "вікна" він оголошує "входи" та "виходи" цього поля. У світі програмного забезпечення це зазвичай означає операції, на які можна викликати вікно (разом з аргументами), а в деяких випадках і типи повернення цих операцій.

Те, що він не робить, - це визначити, що таке семантика цих операцій, хоча це звичайна практика (і дуже хороша практика) документувати їх поблизу декларації (наприклад, за допомогою коментарів) або вибирати правильні умови іменування. Тим не менш, немає гарантій, що ці наміри будуть дотримані.

Ось аналогія: подивіться телевізор, коли він вимкнений. Його інтерфейс - це кнопки, які він має, різні штекери та екран. Його семантика та поведінка полягають у тому, що він приймає входи (наприклад, кабельне програмування) та має виходи (відображення на екрані, звук тощо). Однак, дивлячись на телевізор, який не підключений, ви проектуєте очікувану семантику в інтерфейс. З усього, що ви знаєте, телевізор може просто вибухнути, коли ви підключите його. Однак, виходячи з його "інтерфейсу", ви можете припустити, що він не буде робити кави, оскільки у нього немає води.

В об'єктно-орієнтованому програмуванні інтерфейс зазвичай визначає набір методів (або повідомлень), на які може відповідати екземпляр класу, який має цей інтерфейс.

Що додає плутанини в тому, що в деяких мовах, як, наприклад, Java, існує власне інтерфейс з його мовною семантикою. Наприклад, у Java це набір декларацій методів, без реалізації, але інтерфейс також відповідає типу та підкоряється різним правилам введення тексту.

В інших мовах, як-от C ++, у вас немає інтерфейсів. Клас сам визначає методи, але ви можете думати про інтерфейс класу як декларації неприватних методів. Через те, як C ++ компілюється, ви отримуєте файли заголовків, де ви могли б мати "інтерфейс" класу без фактичної реалізації. Ви також можете імітувати інтерфейси Java з абстрактними класами з чистими віртуальними функціями тощо.

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


Я читаю книгу на «Objective-C» і мені здається, що автори взаємозамінно використовують терміни «протокол» та «інтерфейс». Чи правильно сказати, що "протокол" і "інтерфейс" - це одне і те ж, або я щось пропускаю?
Fazzolini

1
Я б не використовував слово "протокол" для "інтерфейсу". Слово "протокол" передбачає рівень деталізації щодо того, як здійснюються дії. "Інтерфейс" справді - це відмінне слово з чисто англійським визначенням, яке суворо описує, що саме воно є.
OCDev

У програмуванні Windows інтерфейси використовуються досить широко, тому навіть у C ++ ви можете зустріти "інтерфейси" таким чином, щоб об'єкти, від'єднані від реалізації.
Вікторія

166

Розглянемо таку ситуацію:

Ви знаходитесь посеред великої порожньої кімнати, коли зомбі раптом нападає на вас.

У вас немає зброї.

На щастя, у дверях кімнати стоїть людина, яка живе.

"Швидко!" ти кричиш на нього. "Кинь мені щось, з чим я можу вдарити зомбі!"

Тепер подумайте:
ви не вказали (і вам не байдуже), що саме ваш друг вирішить кинути;
... Але це не має значення, якщо:

  • Це щось, що можна кинути (Він не може кинути вам диван)

  • Це щось, за що можна схопитись (сподіваємось, він не кинув шурікен)

  • Це те, що ви можете використати, щоб вирвати мізки зомбі (Це виключає подушки і таке)

Не має значення, отримаєте ви бейсбольну биту чи молоток -
доки вона виконує ваші три умови, ви добре.

Підсумовуючи це:

Коли ви пишете інтерфейс, ви в основному говорите: "Мені потрібно щось, що ..."


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());

Для класу Ігор потрібен секретний номер. Для того, щоб перевірити його, ви хочете ввести те, що буде використовуватися як секретний номер (цей принцип називається Інверсія управління).

Ігровий клас хоче бути «відкритим» щодо того, що насправді створить випадкове число, тому він запитає у своєму конструкторі «все, що має метод 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клас просто намагатиметься викликати будь-який об'єкт, переданий. Якщо об'єкт має метод create (), все добре. Якщо це не так: 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 7. Там інтерфейси були вашим єдиним способом конкретизації такої поведінки. Однак Java 8 представила лямбда-вирази, тому приклад C # можна перетворити на Java дуже легко ( Func<int>стає java.util.function.IntSupplierі =>стає ->).


4

Технічно я би описав інтерфейс як сукупність способів (методів, властивостей, аксесуарів ... словниковий запас залежить від мови, якою ви користуєтесь) взаємодії з об'єктом. Якщо об’єкт підтримує / реалізує інтерфейс, ви можете використовувати всі способи, визначені в інтерфейсі, для взаємодії з цим об’єктом.

Семантично інтерфейс також може містити умови про те, що ви можете, а що не можете робити (наприклад, порядок, у якому ви можете викликати методи) та про те, що, у свою чергу, ви можете припустити про стан об'єкта, враховуючи, як ви взаємодіяли так далеко.


2

Особисто я бачу інтерфейс, як шаблон. Якщо інтерфейс містить визначення методів foo () та bar (), то ви знаєте, що кожен клас, який використовує цей інтерфейс, має методи foo () та bar ().


2

Розглянемо, що людина (користувач або об’єкт) хоче виконати певну роботу. Він зв’яжеться із середньою людиною (Interface), яка матиме контракт з компаніями (об'єкти реального світу, створені за допомогою реалізованих класів). Він визначить небагато видів робіт, які компанії будуть реалізовувати та давати йому результати. Кожна компанія виконуватиме роботу по-своєму, але результат буде однаковим. Як і цей Користувач буде виконувати свою роботу за допомогою єдиного інтерфейсу. Я думаю, що інтерфейс буде виступати як видима частина систем з кількома командами, які будуть визначені внутрішньо реалізованими внутрішніми підсистемами.


1

Інтерфейс відокремлює операції над класом від реалізації всередині. Таким чином, деякі реалізації можуть забезпечити безліч інтерфейсів.

Люди зазвичай описують це як "контракт" для того, що повинно бути доступним у методах класу.

Це абсолютно не план, оскільки це також визначало б реалізацію. Повне визначення класу можна сказати як креслення.


1

Інтерфейс визначає, що повинен наслідувати клас, який успадковує його. Таким чином, кілька класів можуть успадковувати інтерфейс, і через це успадкування ви можете

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

Для отримання додаткової інформації дивіться це http://msdn.microsoft.com/en-us/library/ms173156.aspx


1

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

У цьому визначенні я намагаюся охопити як програмні інтерфейси, де клієнт є деяким модулем, так і людські інтерфейси (наприклад, GUI).

Як уже говорили інші, інтерфейс завжди має деякий контракт за ним, з точки зору входів та результатів. Інтерфейс нічого не обіцяє щодо "як" операцій; це гарантує лише деякі властивості результату, враховуючи поточний стан, вибрану операцію та її параметри.


1

Як зазначено вище, синоніми "контракт" та "протокол" є відповідними.

Інтерфейс містить методи та властивості, які ви можете очікувати, що їх буде викрито класом.

Отже, якщо клас Cheetos Bagреалізує Chip Bagінтерфейс, ви повинні розраховувати на те, що Cheetos Bagвін поводитиметься так само, як і будь-який інший Chip Bag. (Тобто викрийте .attemptToOpenWithoutSpillingEverywhere()метод тощо)


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

Коротше кажучи, основна проблема, яку інтерфейс намагається вирішити, - це відокремити те, як ми використовуємо щось від того, як це реалізовано. Але слід врахувати, що інтерфейс не є договором . Детальніше читайте тут .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.