Consider the following classes representing an Ordering system:
Public Class OrderBase
Public MustOverride Property OrderItem as OrderItemBase
End Class
Public Class OrderItem开发者_JAVA技巧Base
End Class
Now, suppose we want to extend these classes to a more specific set of order classes, keeping the aggregate nature of OrderBase:
Public Class WebOrder
Inherits OrderBase
Public Overrides Property OrderItem as WebOrderItem
End Property
End Class
Public Class WebOrderItem
Inherits OrderItemBase
End Class
The Overriden property in the WebOrder class will cause an error stating that the return type is different from that defined in OrderBase... however, the return type is a subclass of the type defined in OrderBase. Why won't VB allow this?
You can't do that - it's changing the signature defined on the base. To do what you are trying to do you need to use generics:
Public Class OrderBase(Of T As IOrderItem)
Public ReadOnly Property OrderItems As IList(Of T)
End Class
My Visual Basic is rusty so hopefully that is accurate...
You cannot change the signature of your class upon overriding it. You can, however, return a derived type:
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
Alternatively, if you want to enforce the types more strictly, use generics with generic type constraints, as shown below:
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
Or do this if you don't want WebOrder to be a generic class as well:
Public Class WebOrder
Inherits OrderBase(Of WebOrderItem)
Public Overrides ReadOnly Property OrderItem() As WebOrderItem
Get
Return New WebOrderItem()
End Get
End Property
End Class
One approach is to have a protected overridable method, and then have a public non-overridable method which calls the overridable one. Any time the return value for the function in the derived class should change, have a notoverridable override of the overridable method call a new overridable method which returns the more refined type, and also shadow the earlier version of the public function with one that uses the new override. If vb.net allowed one class to both override and shadow the same member, things would be much cleaner, but there's no way to do that.
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
A simpler alternative in some cases may be to have a public overridable MakeCar() function which always returns an object of type Car
, but have a FordFactory also include a MakeFord() function which returns a Ford.
The overridden MakeCar() function would be NotOverridable
and would simply call MakeFord. In some ways, the latter approach can be cleaner, but if there's a common naming convention (e.g. factories have a MakeProduct method which returns the most derived type) it may be useful to use Shadows.
精彩评论