Наследование и интерфейсы VB.Net - PullRequest
1 голос
/ 14 июля 2011

Кто-нибудь намекнул, что я делаю не так в VB.Net?

Module Module1

Interface ISearch(Of T As ISearchResult)
    Function ids() As List(Of T)
End Interface

Interface ISearchResult
    Function id() As String
End Interface

MustInherit Class BasicSearch(Of T As ISearchResult)
    Implements ISearch(Of T)

    MustOverride Function ids() As System.Collections.Generic.List(Of T) Implements ISearch(Of T).ids

End Class

Class Search
    Inherits BasicSearch(Of SearchResult)
    Implements ISearch(Of SearchResult)


    Overrides Function ids() As System.Collections.Generic.List(Of SearchResult)
        Return New List(Of SearchResult)
    End Function
End Class

Class SearchResult
    Implements ISearchResult
    Public Function id() As String Implements ISearchResult.id
        Return "id"
    End Function
End Class

Sub Main()

    Dim foo As New Search()
    Dim bar As Object = foo
    Dim foobar As ISearch(Of ISearchResult) = foo

End Sub

End Module

Третий актерский состав не работает. Почему?

я пропустил урок?

спасибо

Ответы [ 2 ]

1 голос
/ 14 июля 2011

Приведение не работает, потому что foobar - это ISearch(Of ISearchResult), а foo - это ISearch(Of SearchResult, которые несовместимы, и не существует оператора неявного преобразования.

.NET 4.0 ввел концепцию ковариантных и контравариантных параметров универсального типа, которые можно элегантно использовать для решения этой проблемы. Если вы попытаетесь скомпилировать код с VB 10, вы получите эту ошибку.

ошибка BC36757: «Module1.Search» не может быть преобразован в 'Module1.ISearch (Of Module1.ISearchResult)'. Рассмотрите возможность изменения буквы «Т» в определении «Интерфейс ISearch (Of T As Module1.ISearchResult) 'к параметру типа Out,' Out T '.

Следуя рекомендации, вы можете указать, что T является ковариантным в ISearchResult, используя новое ключевое слово Out.

Interface ISearch(Of Out T As ISearchResult)
    Function ids() As List(Of T)
End Interface

К сожалению, теперь мы получаем эту ошибку.

ошибка BC36724: тип 'T' не может использоваться в этом контексте, потому что 'T' параметр типа «Out».

Причина в том, что List(Of T) не является ковариантным. Однако IEnumerable(Of T) есть. Так что это будет хорошо.

Interface ISearch(Of Out T As ISearchResult)
    Function ids() As IEnumerable(Of T)
End Interface

Затем вам нужно будет сделать то же самое изменение с List(Of T) на IEnumerable(Of T) и для других объявлений.

1 голос
/ 14 июля 2011

ISearch(Of SearchResult) не ISearch(Of ISearchResult) - у них разные параметры универсального типа. Search является ISearch(Of SearchResult).


Ответ Брайана охватывает ковариацию и т. Д., Материал для .NET 4, который я планировал добавить к этому вопросу позже (я быстро написал первоначальный ответ, а затем мне пришлось отключиться - к тому времени, когда я вернулся, Брайан ответил)


Чтобы ответить г-н. Мой комментарий - представьте, если у ISearch был другой метод:

Sub AddID(ID as T)

и предполагая, что мы затем реализуем это в Search (который, помните, равен ISearch(Of SearchResult), поэтому T равен SearchResult). И предположим, что у нас было что-то еще, что реализует ISearchResult, скажем:

Public Class BadNews
    Implements ISearchResult

    Public Function id() As String Implements ISearchResult.id
        Return "other"
    Function
End Class

Теперь, если ваш актерский состав сработал, мы могли бы позвонить:

foobar.AddID(New BadNews)

Но это не может работать - реализация AddID, которую мы вызываем, - это реализация, реализованная Search - и эта функция ожидает только получения объектов типа SearchResult.

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