Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以在VB.NET中重写属性并返回派生类型?_Vb.net_Inheritance_Overriding_Covariance - Fatal编程技术网

是否可以在VB.NET中重写属性并返回派生类型?

是否可以在VB.NET中重写属性并返回派生类型?,vb.net,inheritance,overriding,covariance,Vb.net,Inheritance,Overriding,Covariance,考虑以下代表订购系统的类: Public Class OrderBase Public MustOverride Property OrderItem as OrderItemBase End Class Public Class OrderItemBase End Class 现在,假设我们想将这些类扩展到一组更具体的order类,保持OrderBase的聚合性质: Public Class WebOrder Inherits OrderBase

考虑以下代表订购系统的类:

Public Class OrderBase
    Public MustOverride Property OrderItem as OrderItemBase
End Class

Public Class OrderItemBase
End Class
现在,假设我们想将这些类扩展到一组更具体的order类,保持OrderBase的聚合性质:

Public Class WebOrder
    Inherits OrderBase        

    Public Overrides Property OrderItem as WebOrderItem 
    End Property
End Class

Public Class WebOrderItem
    Inherits OrderItemBase
End Class

WebOrder类中被重写的属性将导致一个错误,指出返回类型不同于OrderBase中定义的返回类型。。。但是,返回类型是OrderBase中定义的类型的子类。为什么VB不允许这样做?

您不能这样做-它正在更改基上定义的签名。要执行您试图执行的操作,您需要使用泛型:

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

我的Visual Basic已经生锈了,所以希望它是准确的…

您不能在重写它时更改类的签名。但是,您可以返回派生类型:

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

一种方法是使用受保护的可重写方法,然后使用调用可重写方法的公共非重写方法。任何时候,派生类中函数的返回值应该更改,对可重写方法进行NOTverridable重写调用一个新的可重写方法,该方法返回更精细的类型,并且还使用使用新重写的方法来隐藏公共函数的早期版本。如果vb.net允许一个类同时覆盖和隐藏同一个成员,那么事情会更干净,但是没有办法做到这一点

公共级汽车制造厂
受保护的可重写函数DerivedMakeCar()作为Car
“造一辆车
端函数
公共函数MakeCar()作为Car
Return-DerivedMakeCar()
端函数
末级
公营工厂
继承汽车工厂
受保护的覆盖函数DerivedMakeCar()作为Car
返回DerivedMakeFord()
端函数
受保护的可重写函数DerivedMakeFord()为Ford
“开一辆福特
端函数
公共阴影函数MakeCar()作为福特
返回DerivedMakeFord()
端函数
末级
在某些情况下,一个更简单的替代方法可能是使用一个公共可重写的MakeCar()函数,该函数始终返回类型为
Car
的对象,但FordFactory还包括一个返回Ford的MakeFord()函数


被重写的MakeCar()函数将是不可重写的,只需调用MakeFord即可。在某些方面,后一种方法可能更简洁,但如果有一个通用的命名约定(例如,工厂有一个MakeProduct方法,该方法返回最派生的类型),则使用阴影可能会很有用。

将订单项定义为数组无论如何都是一个坏主意。使用列表或Ienumerable。在我的实际代码中,它们是列表。很抱歉与()混淆。另请参阅的答案,以了解原因和技巧/解决方法。()您的语法还可以,但是转到泛型时,您错过了一件事:您不再需要重写属性——基本实现已经是正确的了。另外,现在我们可能能够为orderItems使用接口而不是基类。我为你清理了它。另外-我加入了我关于使用列表而不是数组的评论。我想你不喜欢它只是恢复。将属性更改为可重写-除此之外,谢谢你为我格式化它。实际上,这是我最初拥有的,但它变得很混乱。在实际项目中,Order类有一个包列表,每个包都有一个OrderItems列表。很快,由于项的嵌套,泛型参数就变成了一英里长。它还使您永远无法返回带有generic PackageBase和OrderItemBase的generic OrderBase。我想我只是不明白,当返回类型是一个子类时,为什么我真的要更改签名?在这种情况下,为什么要更改签名?因此,我对歧义/抽象(我忘记了,所以添加:P)发表了评论。如果您希望返回最低的公共抽象,那么该属性应该返回(OrderItemBase的)IList。不要使用泛型,也不要使用原始签名。不幸的是,这不允许某些人(例如)持有表示某种OrderBase的对象列表,调用OrderItem,并从OrderItemBase派生一些对象。不过,我们可以通过协变接口实现这一点。