2012-02-17 13 views
1

List(Of TKey, TValue)を継承し、いくつかの機能を追加するクラスを作成しました。その目的は、実行時にアイテムを追加するのではなく、初期化するときです。私は実際にクラスから追加/削除メソッドを削除する(現在は継承されたクラスからそれらを公開するので)。VB .Netかなり高度な状況ですが、多くの情報が提供されています

TestAppクラスが表示されている場合は、List(Of String, Integer)をクラスに追加すると正しく動作します。しかし、以下のコードでは、クラスコンストラクタでMe.Add()を使用しようとしました。それを追加するには動作しません。実際には、StringをTKeyに変換できず、IntegerをTValueに変換できないことがわかります。それは真実ではありません!テストアプリでうまく動作します。

アイデア?ここにコードがあります。 VarsクラスとTestアプリケーションの2つのクラス。

注:Me.Add(String, Integer)が動作しないようであっても、クラス内からオーバーライドAdd方法を使用して(同じエラー)

Imports System 
Imports System.Collections.Generic 
Imports System.Text 


Public Class Vars(Of TKey, TValue) 

Inherits List(Of KeyValuePair(Of TKey, TValue)) 

''' <summary> 
'''  Initializes the class and fills with Key->Value Pairs 
''' </summary> 
''' <remarks> 
'''  This does not work when adding directly from the class. When I overload 
''' the Add() function, and call it with a KeyValuePair(Of String, String) in a 
''' class instance it works, see below 
''' </remarks> 
Public Sub New() 
    Dim kv = New KeyValuePair(Of TKey, TValue)("This", 1) 
    Me.Add(kv) 
End Sub 

''' <summary> 
'''  Adds an item to the class by String, Integer 
''' </summary> 
''' <param name="aKey">A String containing the Key of the element to be added.</param> 
''' <param name="aValue">An Integer containing the Value of the element to be added.</param> 
''' <remarks> 
'''  This Works fine when called as in the demo shown below. 
''' </remarks> 
Public Overloads Sub Add(ByVal aKey As TKey, ByVal aValue As TValue) 
    Dim kv = New KeyValuePair(Of TKey, TValue)(aKey, aValue) 
    Me.Add(kv) 
End Sub 

''' <summary> 
'''  Finds a Value stored in the class based on a given Key. 
''' </summary> 
''' <param name="key">A String containing a Key to search for.</param> 
''' <remarks>Works.</remarks> 
Public Function FindByKey(ByVal key As TKey) As List(Of KeyValuePair(Of TKey, TValue)) 
    Return Me.FindAll(Function(item As KeyValuePair(Of TKey, TValue)) (item.Key.Equals(key))) 
End Function 

''' <summary> 
'''  Finds a Key stored in the class based on a given Value. 
''' </summary> 
''' <param name="value">An Integer containing the Value to search for.</param> 
''' <remarks>Works</remarks> 
Public Function FindByValue(ByVal value As TValue) As List(Of KeyValuePair(Of TKey, TValue)) 
    Return Me.FindAll(Function(item As KeyValuePair(Of TKey, TValue)) (item.Value.Equals(value))) 
End Function 

End Class 

Public Class TestApp 
    Shared Sub Main() 
     Dim varTest As Vars(Of String, Integer) = New Vars(Of String, Integer) 
     varTest.Add("Kung", 1) 
     varTest.Add("Foo", 2) 

     For Each var In varTest 
      Console.WriteLine(var.Key & ":" & var.Value) 
     Next 

     'Output would be 
     ' 
     ' Kung:1 
     ' Foo:2 
    End Sub 
End Class 

答えて

7

ここで起こって多くのこと。

  1. 具体的に:あなたのクラスは、一般的なことをを意図していますか?つまり、 あなたはVars(Of String, Integer)Vars(Of Object, DateTime),Vars(Of Double, Object)などを使用していますか?もしそうなら、 あなたがこの行で発生するとよいでしょう:

    Dim kv = New KeyValuePair(Of TKey, TValue)("This", 1) 
    

    TKeyStringではない、とTValueないIntegerのですか? List(Of KeyValuePair(Of TKey, TValue)) に追加できるものは、 KeyValuePairだけでなく、KeyValuePair(Of TKey, TValue)です。

  2. さらに一般的には:List(Of T)is not designed to be inherited from(これはたくさん出てきます。これは最初の例の回答 でした)。 List(Of T)が含まれているクラスを持っており、継承し、その中にアイテムを保持、しかし ではなく、すべての手段によって、あなたはあなたのクラスの パブリックインターフェイスがあること、そしてそれだけでは実装したい正確に何を決定する必要があります。 IListまたはその他の事前定義されたインターフェイスを実装することで、必要な契約が得られることになりますが、必ずしもそうとは限りません。さらに一般的に

  3. :あなた自身が「私は実際に は、クラスからの追加/削除方法を削除したいと思います」と言って見つけたとき、それはあなたがは、そのクラスから継承するべきではありません 巨大なヒントです。 Liskov substitution principleは(約)クラスCから 継承ができるはずであるという何かがCのように扱われることを述べている: あなたがListから継承した場合、発信者はごく自然 に期待AddDeleteにできるようになります。 のパブリックインターフェイスでこれらのメソッドを使用しない場合は、そのクラスから継承しないでください。また、この問題を解決する方法の提案を含めて、ここで他の回答に構築するには

+0

これはすばらしい答えです。私が追加する唯一のことは、新しいクラスについて話すときに、リストの周りのラッパーで、必要なものだけを公開できることです。それはリストを含み、それを再作成する作業を保存しますが、ほとんどの呼び出しをそのリストに渡します。私はこれがほぼ確実に望ましいソリューションであると考えているので、その価値について言及しています。とにかくこのコメントでは、ここにそれがない場合。 :) – Chris

+0

偉大な答え、ちょうど私が聞く必要があった。 –

0

、これは構図ではなく、継承よりも、使用されるべきである古典的なケースです。プライベートメンバとしてリストをラップする型を作成します。新しいタイプには、必要なメソッドとプロパティのみがあります。実装するのは簡単ですが、新しいタイプの各メソッドまたはプロパティは単に元のメソッドを呼び出すだけなので、やや面倒です。

関連する問題