Можно ли переопределить свойство и вернуть производный тип в VB.NET? - PullRequest
6 голосов
/ 07 мая 2010

Рассмотрим следующие классы, представляющие систему заказа:

Public Class OrderBase
    Public MustOverride Property OrderItem as OrderItemBase
End Class

Public Class OrderItemBase
End Class

Теперь предположим, что мы хотим расширить эти классы до более определенного набора классов заказов, сохраняя агрегированную природу OrderBase:

Public Class WebOrder
    Inherits OrderBase        

    Public Overrides Property OrderItem as WebOrderItem 
    End Property
End Class

Public Class WebOrderItem
    Inherits OrderItemBase
End Class

Свойство Overriden в классе WebOrder вызовет ошибку, сообщающую, что возвращаемый тип отличается от определенного в OrderBase ... однако возвращаемый тип является подклассом типа, определенного в OrderBase. Почему VB не допустит этого?

Ответы [ 3 ]

8 голосов
/ 07 мая 2010

Вы не можете сделать это - это изменение подписи, определенной на базе. Чтобы сделать то, что вы пытаетесь сделать, вам нужно использовать дженерики:

Public Class OrderBase(Of T As IOrderItem)
    Public ReadOnly Property OrderItems As IList(Of T)
End Class

Мой Visual Basic ржавый, так что надеюсь, что он точный ...

4 голосов
/ 07 мая 2010

Вы не можете изменить подпись вашего класса после переопределения. Однако вы можете вернуть производный тип:

Public Overrides Property OrderItem() as OrderItemBase
    Get
        Return New WebOrderItem()
    End Get
End Property

Public Sub Whatever()
    Dim item As WebOrderItem = DirectCast(OrderItem, WebOrderItem)
End Sub

В качестве альтернативы, если вы хотите более строго применять типы, используйте обобщенные типы с ограничениями обобщенных типов, как показано ниже:

Public MustInherit Class OrderBase(Of T As OrderItemBase)
    Public MustOverride ReadOnly Property OrderItem() As T
End Class

Public Class OrderItemBase
End Class

Public Class WebOrder(Of T As WebOrderItem)
    Inherits OrderBase(Of T)

    Public Overrides ReadOnly Property OrderItem() As T
        Get
            Return New WebOrderItem()
        End Get
    End Property
End Class

Public Class WebOrderItem
    Inherits OrderItemBase
End Class

Или сделайте это, если вы не хотите, чтобы WebOrder также был универсальным классом:

Public Class WebOrder
    Inherits OrderBase(Of WebOrderItem)

    Public Overrides ReadOnly Property OrderItem() As WebOrderItem
        Get
            Return New WebOrderItem()
        End Get
    End Property
End Class
3 голосов
/ 28 октября 2010

Один из подходов состоит в том, чтобы иметь защищенный переопределяемый метод, а затем иметь общедоступный не переопределяемый метод, который вызывает переопределяемый. Каждый раз, когда возвращаемое значение для функции в производном классе должно измениться, переопределение notoverridable переопределяемого метода вызывает новый переопределяемый метод, который возвращает более уточненный тип, а также скрывает более раннюю версию публичной функции с той, которая использует новое переопределение. Если бы vb.net позволял одному классу переопределять и скрывать одного и того же члена, все было бы намного чище, но сделать это невозможно.

Public Class CarFactory
  Protected Overridable Function DerivedMakeCar() as Car
    ' make a car
  End Function

  Public Function MakeCar() as Car
    Return DerivedMakeCar()
  End Function

End Class

Public Class FordFactory
  Inherits CarFactory

  Protected Overrides Function DerivedMakeCar() As Car
    Return DerivedMakeFord()
  End Function

  Protected Overridable Function DerivedMakeFord() As Ford
    ' Make a Ford
  End Function

  Public Shadows Function MakeCar() As Ford
    Return DerivedMakeFord()
  End Function

End Class

В некоторых случаях более простой альтернативой может быть использование общедоступной переопределяемой функции MakeCar (), которая всегда возвращает объект типа Car, но в FordFactory также имеется функция MakeFord (), которая возвращает Ford.

Переопределенная функция MakeCar () будет NotOverridable и будет просто вызывать MakeFord. В некотором смысле последний подход может быть чище, но если существует общее соглашение об именах (например, на фабриках есть метод MakeProduct, который возвращает наиболее производный тип), может быть полезно использовать тени.

...