2016-10-26 3 views
-1

Fruitという名前のクラスとFruitStandという名前のクラスを考えてみましょう。FruitStandという一般的なListを含み、プロパティ(Contents)を公開して、クラスのフルーツ。VB.NETサブクラス化されたアイテムのリストコレクションを含むクラスのサブクラス

今、FruitのサブクラスであるAppleクラスを作成したいと思います.FruitStandのサブクラスであるAppleCartというクラスが必要です。 AppleCartの一般的なListの内容には、Appleクラスのインテンスのみが含まれます。私が望むのは、AppleCartのコンシューマーに、Contentsプロパティから返された要素をAppleからFruitからキャストする必要がないことです。

これは私が精神的な邪魔をしているだけの単純なものだと思っています。

+0

AppleCartにはAppleのみを含めることができますが、なぜそれをキャストする必要がありますか? – Plutonix

+0

AppleCartがFruitStandから継承するのではなく、おそらくインターフェイス(例えば、IFruitVendor(of T))があなたの望むことをするでしょう。 – Plutonix

+0

スーパークラスを取り戻す(FruitStand)Appleのリストではなく、フルーツのリストを返します。そのため、消費者は、Appleに固有のプロパティにアクセスするために、列挙者から返されたFruitをAppleにキャストする必要があります。 AppleカートにはApplesのみが含まれているため、Applesのみがリストに追加されます。 – rcp

答えて

2

その宣言にFruitから派生するクラスを指定するには、派生クラスを強制的にFruitStandクラス、上の一般的な制約を使用することができます。もしどちらかがあなたのFruitStand一般的なので、のように行います:

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 
+0

私は非常に単純なものが欠けていることを知っていました。ありがとう! – rcp

2

あなたがジェネリックを使用することができ

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 
1

が、私は3つのオプションを見ていると同じからそれらの両方を導き出す

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との関係を断つ、新たに抽出されました基底クラス(私はこれがneatestオプションだと思う):私は、派生を封印してきたいずれの場合も

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 
+0

これら3つのアプローチはすべてメリットがあります。私の目的のために、最も簡単なアプローチ(FruitStandジェネリックの作成)はthe_lotusの答えに述べられているように十分でした。 – rcp

関連する問題