Реализовать интерфейс с помощью частного метода в vb.net

Я был в шоке от этого. Может ли кто-нибудь объяснить, почему это работает? Хороший пример того, когда его использовать, также будет приятным.

Public Interface IFoo
  Sub DoIt()
End Interface

Public Class Bar
  Implements IFoo

  Private DoIt() implements IFoo.DoIt
End Class

...

Dim b as new Bar()
b.DoIt() 'error
CType(b, IFoo).DoIt() 'no error

Ответ 1

Наличие реализации частного интерфейса в основном позволяет вам реализовать интерфейс без необходимости испортить API вашего класса. Вы можете реализовать IFoo, но только те API, которые рассматривают вас как IFoo, должны знать это.

MSDN говорит

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

Ответ 2

Я был в шоке от этого. Может ли кто-нибудь объяснить, почему это работает? Хороший пример того, когда его использовать, также будет приятным.

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

Я не могу прокомментировать, почему команда .NET Framework почувствовала, что эта функция действительно необходима. Иногда это может усиливать инкапсуляцию, но я не уверен в этом. В любом случае что-то очень похожее всегда было бы возможно с использованием композиции вместо наследования (интерфейса).

Ответ 3

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

Public Class ObservableList(Of T)
    Implements INotifyCollectionChanged, 
               IList, 
               IList(Of T)
End Class

Когда оба ILists реализованы, мы получаем много дублирующих функций. Некоторые используют одну и ту же подпись и могут реализовывать обе функции IList, такие как Clear. Но некоторые из не общих функций имеют дело с объектами, а не с общим. Таким образом, для функции "Добавить" я бы сделал обе реализации, но установил для него не общий вариант, чтобы упростить использование класса.

Public Sub Add(item As T) Implements System.Collections.Generic.ICollection(Of T).Add
    'Add item to collection
End Sub

Private Function Add1(item As Object) As Integer Implements System.Collections.IList.Add
    'Add item to collection
End Function

Таким образом, класс может быть передан и использован как IList, но кодер будет использовать его как IList (Of T) без потенциального беспорядка перегрузки.