Як Go покращує продуктивність роботи з "неявними" інтерфейсами, і як це порівнюється з поняттям методів розширення C #?


21

У підручнику Go Go вони пояснюють, як працюють інтерфейси:

Іти не має занять. Однак можна визначити методи за типами структури. Приймач методу з'являється в своєму списку аргументів між Func ключовим словом і ім'ям методу.

type Vertex struct {
    X, Y float64
}

func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

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

Це єдиний спосіб створити інтерфейс у Go. Далі Google пояснює, що:

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

Неявні інтерфейси відокремлюють пакети реалізації від пакетів, що визначають інтерфейси: і це не залежить від іншого.

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

Це все звучить підозріло, як Методи розширення в C # , за винятком того, що методи в Go безжально поліморфні; вони працюватимуть на будь-якому типі, який їх реалізує.

Google стверджує, що це заохочує швидкий розвиток, але чому? Ви щось відмовляєтесь, віддаляючись від явних інтерфейсів у C #? Чи можуть методи розширення в C # дозволяють отримати деякі переваги, які мають інтерфейси Go у C #?



1
Ці інтерфейси Go більше нагадують те, що можуть робити шаблони C ++, ніж методи розширення C #. У C # немає нічого подібного до "будь-якого типу, який реалізує методи A і B", але ви можете це зробити, використовуючи шаблони C ++.
svick


Чи не "неявні інтерфейси" є лише формою набору качки?
Аллон Гуралнек

"Хіба не" неявні інтерфейси "є лише формою набору тексту качки?" Інтерфейси Go є прикладом структурного набору тексту. Дуже схожа концепція.
mortdeus

Відповіді:


12

Я взагалі не бачу методів розширення та неявних інтерфейсів однакових.

Спочатку поговоримо з метою.

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

Мета неявних інтерфейсів полягає в тому, щоб ви могли реалізувати інтерфейс на об'єкті, до якого ви не маєте доступу до змін. Це дає вам можливість створити поліморфні відносини між будь-яким об'єктом, який ви пишете самостійно, і будь-яким об'єктом, до якого ви не маєте доступу до внутрішніх даних.

Тепер поговоримо про наслідки.

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

Наслідки неявних інтерфейсів - це кілька речей.

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

Корисність методів розширення в Linq значною мірою пов'язана з їх здатністю переносити реалізацію методу на інтерфейс, зокрема IEnumerableі IQueryable. Хоча ви могли підробити це за допомогою staticметодів у корисному класі, це було б незграбно.
Роберт Харві

@RobertHarvey Не обов'язково точно стверджувати, що він ставить метод на інтерфейс, зауважте, різниця між фактичним методом інтерфейсу та методом розширення: метод інтерфейсу буде реалізований всередині класу, який реалізує цей інтерфейс, і, отже має доступ до набагато більше, ніж будь-який метод розширення. Знову ж таки, це зміна точки зору, коду, реалізованому всередині класу, надається особлива перспектива порівняно з зовнішньою.
Джиммі Хоффа
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.