VB.NET class 的子class 包含子class 项的列表集合

VB.NET Subclass of class containing list collection of subclassed items

考虑一个名为 Fruit 的 class 和一个名为 FruitStand 的 class,它包含一个通用的 Fruit 列表并公开一个 属性(内容)以获得目的的 Fruit 列表在 class.

中迭代 Fruit

现在我想创建一个 class Apple,它是 Fruit 的子class,我想要一个名为 AppleCart 的 class,它是 FruitStand 的子class . AppleCart 中通用列表的内容将只包含 Apple class 的实例。我想要的是能够让 AppleCart 的消费者不必将 Contents 属性 返回的元素从 Fruit.

转换为 Apple

我希望这是简单的事情,我只是遇到了心理障碍。

您可以在 FruitStand class 上使用通用约束,强制派生的 class 指定派生自 Fruit 的 class它的声明

Sub Main()
    Dim ac As New AppleCart({New Apple(), New Apple()})
    For Each a In ac.Fruits
        a.Rot() ' prints "The apple is rotten!"
    Next
    Console.Read()
End Sub

Public Class Fruit
    Public Overridable Sub Rot()
        Console.WriteLine("The fruit is rotten!")
    End Sub
End Class

Public Class Apple
    Inherits Fruit
    Public Overrides Sub Rot()
        Console.WriteLine("The apple is rotten!")
    End Sub
End Class

Public Class FruitStand(Of T As Fruit)
    Private _fruits As List(Of T)
    Public ReadOnly Property Fruits As IEnumerable(Of T)
        Get
            Return _fruits
        End Get
    End Property
    Public Sub New(fruits As IEnumerable(Of T))
        _fruits = fruits.ToList()
    End Sub
End Class

Public Class AppleCart
    Inherits FruitStand(Of Apple)
    Public Sub New(fruits As IEnumerable(Of Apple))
        MyBase.New(fruits)
    End Sub
End Class

您可以使用泛型。

Sub Main()

    Dim cart As New AppleCart

    cart.Fruits.Add(New Apple)

End Sub

Class FruitStand(Of T As Fruit)

    Public Property Fruits As List(Of T)

End Class

Class Fruit

End Class

Class AppleCart
    Inherits FruitStand(Of Apple)

End Class

Class Apple
    Inherits Fruit

End Class

我看到了 3 个选项:您可以像这样使 FruitStand 通用:

Class FruitStand(Of TFruit As Fruit)
  Public ReadOnly Property Contents As List(Of TFruit)
End Class

NotInheritable Class AppleCart
  Inherits FruitStand(Of Apple)
End Class

或者你切断 FruitStandAppleCart 之间的关系,而是从相同的新提取的基础 class 派生它们(我认为这是最简洁的选择):

MustInherit Class FruitStandBase(Of TFruit As Fruit)
  Public ReadOnly Property Contents As List(Of TFruit)
End Class

NotInheritable Class FruitStand
  Inherits FruitStandBase(Of Fruit)
End Class

NotInheritable Class AppleCart
  Inherits FruitStandBase(Of Apple)
End Class

在这两种情况下,我都密封了派生的 AppleCart,因为从它派生的任何类型都无法覆盖 TFruit 的类型。在层次结构中的那个点,Contents 的类型被关闭。

最后,您可以使用阴影来更改更多派生类型中 Contents 的含义。问题是:您必须为基类型的 Contents 属性 使用协变集合(这意味着使用只读接口,例如 IReadOnlyList(Of Fruit) 或数组 - 无论哪种方式失去添加或删除元素的能力):

Class FruitStand

  Public ReadOnly Property Contents As IReadOnlyList(Of Fruit)

  Public Sub New()
    Me.New(New List(Of Fruit))
  End Sub

  Protected Sub New(contents As IReadOnlyList(Of Fruit))
    Me.Contents = contents
  End Sub

End Class

Class AppleCart
  Inherits FruitStand

  Public Shadows ReadOnly Property Contents As IReadOnlyList(Of Apple)
    Get
      Return CType(MyBase.Contents, IReadOnlyList(Of Apple))
    End Get
  End Property

  Public Sub New()
    MyBase.New(New List(Of Apple))
  End Sub

End Class