Гаразд, мій друг, повертайтеся туди, що означає "інтерфейс" у програмуванні.
Який найкращий опис "інтерфейсу".
Для мене інтерфейс - це креслення класу, це найкраще визначення?
Гаразд, мій друг, повертайтеся туди, що означає "інтерфейс" у програмуванні.
Який найкращий опис "інтерфейсу".
Для мене інтерфейс - це креслення класу, це найкраще визначення?
Відповіді:
Інтерфейс - один із найбільш перевантажених та заплутаних термінів у розробці.
Це фактично поняття абстракції та інкапсуляції. Для заданого "вікна" він оголошує "входи" та "виходи" цього поля. У світі програмного забезпечення це зазвичай означає операції, на які можна викликати вікно (разом з аргументами), а в деяких випадках і типи повернення цих операцій.
Те, що він не робить, - це визначити, що таке семантика цих операцій, хоча це звичайна практика (і дуже хороша практика) документувати їх поблизу декларації (наприклад, за допомогою коментарів) або вибирати правильні умови іменування. Тим не менш, немає гарантій, що ці наміри будуть дотримані.
Ось аналогія: подивіться телевізор, коли він вимкнений. Його інтерфейс - це кнопки, які він має, різні штекери та екран. Його семантика та поведінка полягають у тому, що він приймає входи (наприклад, кабельне програмування) та має виходи (відображення на екрані, звук тощо). Однак, дивлячись на телевізор, який не підключений, ви проектуєте очікувану семантику в інтерфейс. З усього, що ви знаєте, телевізор може просто вибухнути, коли ви підключите його. Однак, виходячи з його "інтерфейсу", ви можете припустити, що він не буде робити кави, оскільки у нього немає води.
В об'єктно-орієнтованому програмуванні інтерфейс зазвичай визначає набір методів (або повідомлень), на які може відповідати екземпляр класу, який має цей інтерфейс.
Що додає плутанини в тому, що в деяких мовах, як, наприклад, Java, існує власне інтерфейс з його мовною семантикою. Наприклад, у Java це набір декларацій методів, без реалізації, але інтерфейс також відповідає типу та підкоряється різним правилам введення тексту.
В інших мовах, як-от C ++, у вас немає інтерфейсів. Клас сам визначає методи, але ви можете думати про інтерфейс класу як декларації неприватних методів. Через те, як C ++ компілюється, ви отримуєте файли заголовків, де ви могли б мати "інтерфейс" класу без фактичної реалізації. Ви також можете імітувати інтерфейси Java з абстрактними класами з чистими віртуальними функціями тощо.
Інтерфейс, безумовно, не є кресленням для класу. План за одним визначенням - це "детальний план дій". Інтерфейс нічого не обіцяє щодо дії! Джерело плутанини полягає в тому, що в більшості мов, якщо у вас тип інтерфейсу, який визначає набір методів, клас, який реалізує його, «повторює» ті самі методи (але надає визначення), тому інтерфейс виглядає як скелет або контур класу.
Розглянемо таку ситуацію:
Ви знаходитесь посеред великої порожньої кімнати, коли зомбі раптом нападає на вас.
У вас немає зброї.
На щастя, у дверях кімнати стоїть людина, яка живе.
"Швидко!" ти кричиш на нього. "Кинь мені щось, з чим я можу вдарити зомбі!"
Тепер подумайте:
ви не вказали (і вам не байдуже), що саме ваш друг вирішить кинути;
... Але це не має значення, якщо:
Це щось, що можна кинути (Він не може кинути вам диван)
Це щось, за що можна схопитись (сподіваємось, він не кинув шурікен)
Це те, що ви можете використати, щоб вирвати мізки зомбі (Це виключає подушки і таке)
Не має значення, отримаєте ви бейсбольну биту чи молоток -
доки вона виконує ваші три умови, ви добре.
Підсумовуючи це:
Коли ви пишете інтерфейс, ви в основному говорите: "Мені потрібно щось, що ..."
Інтерфейс - це договір, який ви повинні виконати або надати йому, залежно від того, чи ви виконавець чи користувач.
Я не думаю, що "план" - це не хороше слово. Креслення розповідає, як щось побудувати. Інтерфейс спеціально уникає розповідати, як щось будувати.
Інтерфейс визначає, як можна взаємодіяти з класом, тобто які методи він підтримує.
Для мене інтерфейс - це креслення класу, це найкраще визначення?
Ні. План зазвичай включає внутрішні. Але інтерфейс - це лише те, що видно на зовнішній стороні класу ... або точніше, сімейство класів, які реалізують інтерфейс.
Інтерфейс складається з підписів методів і значень констант, а також (типово неофіційного) «поведінкового контракту» між класами, які реалізують інтерфейс, та іншими, які його використовують.
У програмуванні інтерфейс визначає, якою буде поведінка об'єкта, але він фактично не визначає поведінку. Це договір, який гарантує, що певний клас може щось зробити.
Розглянемо цей фрагмент коду 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
і =>
стає ->
).
Технічно я би описав інтерфейс як сукупність способів (методів, властивостей, аксесуарів ... словниковий запас залежить від мови, якою ви користуєтесь) взаємодії з об'єктом. Якщо об’єкт підтримує / реалізує інтерфейс, ви можете використовувати всі способи, визначені в інтерфейсі, для взаємодії з цим об’єктом.
Семантично інтерфейс також може містити умови про те, що ви можете, а що не можете робити (наприклад, порядок, у якому ви можете викликати методи) та про те, що, у свою чергу, ви можете припустити про стан об'єкта, враховуючи, як ви взаємодіяли так далеко.
Особисто я бачу інтерфейс, як шаблон. Якщо інтерфейс містить визначення методів foo () та bar (), то ви знаєте, що кожен клас, який використовує цей інтерфейс, має методи foo () та bar ().
Розглянемо, що людина (користувач або об’єкт) хоче виконати певну роботу. Він зв’яжеться із середньою людиною (Interface), яка матиме контракт з компаніями (об'єкти реального світу, створені за допомогою реалізованих класів). Він визначить небагато видів робіт, які компанії будуть реалізовувати та давати йому результати. Кожна компанія виконуватиме роботу по-своєму, але результат буде однаковим. Як і цей Користувач буде виконувати свою роботу за допомогою єдиного інтерфейсу. Я думаю, що інтерфейс буде виступати як видима частина систем з кількома командами, які будуть визначені внутрішньо реалізованими внутрішніми підсистемами.
Інтерфейс відокремлює операції над класом від реалізації всередині. Таким чином, деякі реалізації можуть забезпечити безліч інтерфейсів.
Люди зазвичай описують це як "контракт" для того, що повинно бути доступним у методах класу.
Це абсолютно не план, оскільки це також визначало б реалізацію. Повне визначення класу можна сказати як креслення.
Інтерфейс визначає, що повинен наслідувати клас, який успадковує його. Таким чином, кілька класів можуть успадковувати інтерфейс, і через це успадкування ви можете
Для отримання додаткової інформації дивіться це http://msdn.microsoft.com/en-us/library/ms173156.aspx
На мою думку, інтерфейс має ширше значення, ніж те, що зазвичай з ним асоціюється у Java. Я б визначив "інтерфейс" як сукупність доступних операцій з деякою загальною функціональністю, яка дозволяє контролювати / контролювати модуль.
У цьому визначенні я намагаюся охопити як програмні інтерфейси, де клієнт є деяким модулем, так і людські інтерфейси (наприклад, GUI).
Як уже говорили інші, інтерфейс завжди має деякий контракт за ним, з точки зору входів та результатів. Інтерфейс нічого не обіцяє щодо "як" операцій; це гарантує лише деякі властивості результату, враховуючи поточний стан, вибрану операцію та її параметри.
Як зазначено вище, синоніми "контракт" та "протокол" є відповідними.
Інтерфейс містить методи та властивості, які ви можете очікувати, що їх буде викрито класом.
Отже, якщо клас Cheetos Bag
реалізує Chip Bag
інтерфейс, ви повинні розраховувати на те, що Cheetos Bag
він поводитиметься так само, як і будь-який інший Chip Bag
. (Тобто викрийте .attemptToOpenWithoutSpillingEverywhere()
метод тощо)
Звичайне визначення - інтерфейс - це договір, який визначає методи, які повинні бути реалізовані класом, який його реалізує.
Визначення інтерфейсу з часом змінювалося. Чи вважаєте ви, що в інтерфейсі є лише декларації методів? Що про статичні кінцеві змінні та що про визначення за замовчуванням після Java 5.
Інтерфейси були введені в Java через проблему Diamond з багаторазовим спадкуванням, і саме це вони і мають намір зробити.
Інтерфейси - це конструкції, які були створені для усунення проблеми множинної спадковості та можуть мати абстрактні методи, визначення за замовчуванням та статичні кінцеві змінні.
Межа, через яку спілкуються дві системи.
Інтерфейси - це те, як деякі мови OO досягають спеціального поліморфізму . Спеціальний поліморфізм - це просто функції з однаковими назвами, що працюють на різних типах.
Коротше кажучи, основна проблема, яку інтерфейс намагається вирішити, - це відокремити те, як ми використовуємо щось від того, як це реалізовано. Але слід врахувати, що інтерфейс не є договором . Детальніше читайте тут .