Здесь есть несколько замечательных ответов на эти вопросы, которые касаются всевозможных подробностей об интерфейсах и коде слабой связи, инверсии управления и так далее. Есть несколько довольно бурных дискуссий, поэтому я хотел бы воспользоваться возможностью, чтобы немного разбить вещи, чтобы понять, почему интерфейс полезен.
Когда я впервые начал знакомиться с интерфейсами, меня тоже смутила их актуальность. Я не понимал, зачем они вам нужны. Если мы используем такой язык, как Java или C #, у нас уже есть наследование, и я рассматривал интерфейсы как более слабую форму наследования и подумал: «Зачем беспокоиться?» В каком-то смысле я был прав, вы можете думать об интерфейсах как о некой слабой форме наследования, но, помимо этого, я наконец понял их использование в качестве языковой конструкции, думая о них как о средстве классификации общих черт или поведения, которые проявляются потенциально много не связанных классов объектов.
Например, скажем, у вас есть игра для SIM-карты и у вас есть следующие классы:
class HouseFly inherits Insect {
void FlyAroundYourHead(){}
void LandOnThings(){}
}
class Telemarketer inherits Person {
void CallDuringDinner(){}
void ContinueTalkingWhenYouSayNo(){}
}
Ясно, что эти два объекта не имеют ничего общего с точки зрения прямого наследования. Но можно сказать, что они оба раздражают.
Допустим, в нашей игре должна быть какая-то случайная вещь, которая раздражает игрока, когда он ужинает. Это может быть HouseFly
, Telemarketer
или и то, и другое - но как сделать это с помощью одной функции? И как вы попросите разные типы объектов одинаково «делать то, что их раздражает»?
Ключ к пониманию состоит в том, что и Telemarketer
, и HouseFly
имеют общее, слабо интерпретируемое поведение, даже если они не похожи друг на друга с точки зрения их моделирования. Итак, давайте создадим интерфейс, который оба могут реализовать:
interface IPest {
void BeAnnoying();
}
class HouseFly inherits Insect implements IPest {
void FlyAroundYourHead(){}
void LandOnThings(){}
void BeAnnoying() {
FlyAroundYourHead();
LandOnThings();
}
}
class Telemarketer inherits Person implements IPest {
void CallDuringDinner(){}
void ContinueTalkingWhenYouSayNo(){}
void BeAnnoying() {
CallDuringDinner();
ContinueTalkingWhenYouSayNo();
}
}
Теперь у нас есть два класса, каждый из которых может по-своему раздражать. И им не обязательно быть производными от одного и того же базового класса и иметь общие неотъемлемые характеристики - им просто нужно выполнять контракт IPest
- этот контракт прост. Вам просто нужно BeAnnoying
. В связи с этим можно смоделировать следующее:
class DiningRoom {
DiningRoom(Person[] diningPeople, IPest[] pests) { ... }
void ServeDinner() {
when diningPeople are eating,
foreach pest in pests
pest.BeAnnoying();
}
}
Здесь у нас есть столовая, которая принимает множество посетителей и множество вредителей - обратите внимание на использование интерфейса. Это означает, что в нашем маленьком мире член массива pests
может быть объектом Telemarketer
или объектом HouseFly
.
Метод ServeDinner
вызывается, когда подается ужин, и наши люди в столовой должны есть. В нашей маленькой игре именно тогда наши вредители делают свою работу - каждому вредителю дана инструкция через IPest
интерфейс, как надоедать. Таким образом, мы можем легко заставить и Telemarketers
, и HouseFlys
раздражать по-своему - нас волнует только то, что в объекте DiningRoom
есть вредитель, нам все равно, что это такое, и они могут не имеют ничего общего с другими.
Этот очень надуманный пример псевдокода (который затянулся намного дольше, чем я ожидал) просто предназначен для иллюстрации того, что, наконец, пролило свет на меня с точки зрения того, когда мы можем использовать интерфейс. Заранее прошу прощения за глупость этого примера, но надеюсь, что он поможет в вашем понимании. И, конечно же, другие опубликованные ответы, которые вы здесь получили, действительно охватывают весь спектр использования интерфейсов сегодня в шаблонах проектирования и методологиях разработки.
person
Peter Meyer
schedule
21.12.2008
List lst = new ArrayList();
просто означает, что вы ограничиваете, какие функции для созданного объекта вам доступны, что совершенно глупо. Эта странная конструкция продолжает распространяться учителями и книгами Java без всякой мыслимой причины. - person Nyerguds   schedule 06.01.2017