Я был шокирован этим. Может ли кто-нибудь объяснить, почему это работает? Было бы неплохо и хороший пример того, когда это использовать.
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





I was kind of shocked by this. Could someone explain why this works? A good example of when to use it would also be nice.
Эта концепция во многом аналогична явной реализации интерфейса в C#. Там вы также можете получить доступ к члену интерфейса, только если вы явно приведете тип к этому интерфейсу.
Я не могу комментировать Зачем, но команда .NET framework посчитала, что эта функция действительно необходима. Иногда это может усилить инкапсуляцию, но я в этом не уверен. В любом случае всегда можно было бы сделать нечто очень похожее, используя композицию вместо (интерфейсного) наследования.
Когда член является «частным», он служит той же цели, что и явная реализация интерфейса C#, и имеет в основном ту же семантику (явное выражение C# было бы эквивалентно частной реализации в стиле vb с уникальным случайным частным именем). Большое преимущество подхода vb возникает при реализации интерфейсов с функциями Protected Overridable. Затем производные классы могут реализовать интерфейс в терминах родительской реализации, что невозможно в C# без добавления постороннего уровня косвенности.
Реализация частного интерфейса в основном просто позволяет вам реализовать интерфейс, не запутывая API вашего класса. Вы можете реализовать IFoo, но это должны знать только те API, которые относятся к вам как к IFoo.
MSDN говорит
You can use a private member to implement an interface member. When a private member implements a member of an interface, that member becomes available by way of the interface even though it is not available directly on object variables for the class.
Первая часть вопроса была рассмотрена в других сообщениях, но я не видел примера. Я обычно использую это при реализации универсальных интерфейсов и их неуниверсальных аналогов. Например, если я хочу создать общий ObservableList, мне нужно реализовать оба интерфейса IList.
Public Class ObservableList(Of T)
Implements INotifyCollectionChanged,
IList,
IList(Of T)
End Class
Когда реализованы оба списка IL, мы получаем множество повторяющихся функций. Некоторые имеют одну и ту же сигнатуру и могут реализовывать обе функции IList, такие как Clear. Но некоторые из неуниверсальных функций работают с объектами, а не с универсальными. Итак, для функции Add я бы сделал обе реализации работающими, но установил неуниверсальную версию частной, чтобы упростить использование класса.
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) без потенциального беспорядка из-за перегрузки.
Итак, этот код работает? Я удивлен. Кажется, очень противоречит идее интерфейса.