Is it possible to override a property and return a derived type in VB.NET?

Consider the following classes representing the ordering system:

Public Class OrderBase Public MustOverride Property OrderItem as OrderItemBase End Class Public Class OrderItemBase End Class 

Now suppose we want to extend these classes to a more specific set of order classes, while preserving 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 throws an error indicating that the return type is different from the type defined in OrderBase ... however, the return type is a subclass of the type defined in OrderBase. Why doesn't VB allow this?

+6
override inheritance covariance
source share
3 answers

You cannot do this - this is a change in 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's for sure ...

+7
source share

You cannot change the signature of your class by 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 strictly adhere to types, 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 do not want WebOrder to also be a common class:

 Public Class WebOrder Inherits OrderBase(Of WebOrderItem) Public Overrides ReadOnly Property OrderItem() As WebOrderItem Get Return New WebOrderItem() End Get End Property End Class 
+4
source share

One approach is to have a secure override method, and then have a public method that does not support forwarding, which calls the override. Anytime a return value for a function in a derived class needs to change, override the overridden method that calls the new overridden method, which returns a more refined type, and also obscures the earlier version of the public function to the one that uses the new override. If vb.net allowed one class to redefine and shade the same member, everything would be much cleaner, but there would be no way to do this.

 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 might be to have a publicly redefined function MakeCar () that always returns an object of type Car , but FordFactory also has a MakeFord () function that returns Ford.

The overridden MakeCar () function will be NotOverridable and just call MakeFord. In a sense, the latter approach might be cleaner, but if there is a general naming convention (for example, factories have a MakeProduct method that returns the most derived type), it can be useful to use Shadows.

+3
source share

All Articles