Кодирование к интерфейсам? [дубликат]

Этот вопрос уже имеет ответ здесь:

Я хочу укрепить свое понимание "кодирования для взаимодействия через интерфейс" с понятием. Насколько я понимаю каждый создает интерфейсы для формирования рисунка ожидаемой функциональности и затем реализует эти "контракты" в реальных классах. Для использования интерфейса, можно просто назвать методы на экземпляре реального класса.

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

На основе вышеупомянутого:

  1. Есть ли какие-либо ошибки в моем понимании "кодирования к интерфейсам"?
  2. Есть ли какие-либо преимущества кодирования к интерфейсам, которые я пропустил?

Спасибо.

17
задан Ari 28 December 2009 в 18:21
поделиться

8 ответов

Только одна возможная поправка:

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

Вызов методов осуществляется по ссылке на интерфейс типа, в котором в качестве реализации используется конкретный класс:

List<String> l = new ArrayList<String>();
l.add("foo");
l.add("bar");

Если вы решили перейти на другую реализацию List, то код клиента работает без изменений:

List<String> l = new LinkedList<String>();

Это особенно удобно для сокрытия деталей реализации, автогенерации прокси и т.п.

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

.
16
ответ дан 30 November 2019 в 12:19
поделиться

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

Не имеет значения, SanDisk это или Titanium (даже не уверен, что это бренд), размер / цвет тоже не имеет значения. На самом деле, единственное, что имеет значение, это то, что он не сломан (читаемый) и что он подключается к USB.

Ваш USB флэш-накопитель соблюдает контракт, это, по сути, интерфейс. Можно предположить, что он выполняет некоторые очень основные обязанности:

  1. Подключается к USB
  2. Соблюдает контрактный метод CopyDataTo:

    общедоступный интерфейс IUSB { void CopyDataTo(string somePath); // используется для копирования данных с диска с миниатюрами на... }

  3. Выполняется договорным методом CopyDataFrom:

    public Interface IUSB { void CopyDataFrom(); // используется для копирования данных с ПК на накопитель для миниатюр }

Ок, возможно, не эти методы, но интерфейс IUSB - это всего лишь контракт, который поставщики дисков с миниатюрами должны соблюдать, чтобы обеспечить функциональность на различных платформах/поставщиках. Поэтому SanDisk выпускает свой флеш-накопитель по интерфейсу:

public class SanDiskUSB : IUSB
 {
  //todo: define methods of the interface here
 }

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

.
5
ответ дан 30 November 2019 в 12:19
поделиться

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

.
4
ответ дан 30 November 2019 в 12:19
поделиться

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

.
2
ответ дан 30 November 2019 в 12:19
поделиться

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

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

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

Вроде того. Самое главное, это позволяет писать API, которые берут параметры с типами интерфейсов. Пользователи API затем могут передавать свои собственные классы (реализующие эти интерфейсы), и вы будете работать над этими классами, даже если их еще не существовало на момент написания (например, java.util.Arrays.sort(), имея возможность сортировать все, что реализует Comparable или поставляется с подходящим Comparator).

С точки зрения дизайна, интерфейсы позволяют/выполняют четкое разделение между контрактами API и деталями реализации.

.
4
ответ дан 30 November 2019 в 12:19
поделиться

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

.
1
ответ дан 30 November 2019 в 12:19
поделиться

Я думаю, что вы могли намекнуть на это, но я считаю, что одним из самых больших преимуществ кодирования интерфейса является то, что вы разрушаете зависимость от конкретной реализации. Вы можете достичь свободной связи и облегчить переключение конкретных реализаций, не меняя большого количества кода. Если вы только учитесь, то я бы взглянул на различные шаблоны дизайна и на то, как они решают проблемы путем кодирования на интерфейсы. Читайте книгу Сначала голову: Шаблоны проектирования очень помогли мне.

0
ответ дан 30 November 2019 в 12:19
поделиться

Как я понимаю, создаются интерфейсы для разграничения ожидаемого функционала, а затем эти "контракты" реализуются в конкретных классах.

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

Это позволит растянуть мышление в полиморфизм следующим образом.

SoundMaker sm = new Duck();<br/>
SoundMaker sm1 = new ThunderousCloud();

sm.makeSound(); // quack, calls all sorts of stuff like larynx, etc.<br/>
sm1.makeSound(); // BOOM!, completely different operations here...
0
ответ дан 30 November 2019 в 12:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: