Отделение определения интерфейса от его реализации - PullRequest
0 голосов
/ 22 марта 2020

Во время Тура по Go представлен следующий отрывок, но я не мог придать ему особого значения (думаю, мне не хватает OOP знаний).

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

Чем выгоден decoupling a definition of an interface from its implementation? Моя первоначальная мысль заключается в том, что этот подход значительно снижает «жесткость» (также значимость) интерфейсов ... это просто syntacti c -sugar и все на самом деле "работает как обычно" под капотом?

Спасибо за ваше время.

1 Ответ

2 голосов
/ 22 марта 2020

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

type X struct {...}

func (X) f()
func (X) g()
func (X) h()

Тип X имеет три метода: f(), g(), h(). Если у вас есть структура данных или функция, которая должна вызывать метод f(), вы можете определить интерфейс:

type FIntf interface {
   f()
}

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

Если в другом модуле вам нужны g() и h(), вы можете определить интерфейс там:

type GIntf interface {
  g()
  h()

и теперь X реализует GIntf.

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

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

Утиная печать также обеспечивает безопасность типов при вызове методов. Например, если у вас есть функция, которая должна вызывать метод x() и y() одного из своих аргументов, определите интерфейс, содержащий x() и y(), и используйте утверждение типа для проверки аргумента, реализует эти два методы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...