2011-12-10 15 views
2

私も工場の親クラスを持っています。たとえば、次のように継承されたクラスでクラスの戻り値の型を持つ関数を持つことはできますか? VB.NET

Public Class Factory 
    Public Function clone() as Factory 
     ' Some logic here 
     ' return something 
    End Function 

    Public Function all() as List (Of Factory) 
     ' Some logic here 
     ' return something 
    End Function 
End Class 

そして私は、継承された1によって呼び出されたときに適切な拡張されたオブジェクトを生成するファクトリクラスに抑揚を使用することができます継承された1

Public Class BookFactory 
    inherits Factory 
End Class 

myBookFactory.clone()BookFactoryインスタンスを返すだけでなく、Factoryインスタンスを返します。

問題:BookFactoryのインスタンスは、Factoryであり、BookFactoryではないため、Factoryとしてキャストされます。

私はそう返された値が正しくキャストし、これを毎回行うことを避けることになる

Public Class Factory 
    Public Function clone() as Me.GetType() 
     ' Some logic here 
     ' return something 
    End Function 

    Public Function all() as List (Of Me.GetType()) 
     ' Some logic here 
     ' return something 
    End Function 
End Class 

ような何かをしたいと思います:

Dim myBookFactory2 = DirectCast(myBookFactory1.clone(), myBookFactory1.getType()) 

私はこれをどのように行うことができますか?

+1

ここでは、工場のパターンを真剣に殺しています。しかし、消費者が派生したタイプを気にしている場合は、キャストが必要です。それはいけません。フレームワーク内のXmlWriter.Create()と比較してください。 –

答えて

2

これは、共変な戻り値の型を要求するバリエーションです。ご存じのように、これはVB.NET(またはC#の場合)ではサポートされていません。通常、これは仮想メソッドのオーバーライドのコンテキストで尋ねられますが、まだ許可されていません。いくつかの選択肢があり、それぞれに独自の長所と短所があります。

これはIComparable<T>は、最も一般的に実装されている方法に類似している派生クラスを指定するには、汎用的なテンプレート引数を使用します。あなたはファクトリー(例:Factory(Of T {New, Factory(Of T)}))にNew制約を追加することができた場合

Public Class Factory(Of T As Factory) 
    Public Function Clone() As T 
     'use GetType(T) to determine derived type 
    End Function 
End Class 

Public Class BookFactory 
    Inherits Factory(Of BookFactory) 
End Class 

また、ベース・クラスは、リフレクションを使用して避けることができるかもしれません。

しかし、これは次のようにクラスを宣言するの偶発(または悪意のある)ミスを防ぐことはできません。

Public Class EvilFactory 
    Inherits Factory(Of BookFactory) 
    'hmmm, now clone will be making the wrong type 
End Class 

また、このアプローチは、それが不可能に頼ることなく、異なる種類の工場のリストを作成することができますFactory(Of T)以下の別の基底クラスに追加するか、リストをオブジェクトとして宣言します。

派生クラスに対して、必要な特定のタイプを返す新しいメソッドを作成します。

Public Class Factory 
    Public Function Clone() As Factory 
     'create derived class, but return as base 
    End Function 
End Class 

Public Class BookFactory 
    Inherits Factory 

    Public Function CloneBooks() As BookFactory 
     Return CType(Me.Clone(), BookFactory) 
    End Function 
End Class 

これは、あなたがBookFactoryを持っているし、別のBookFactoryを取得したい知っているときあなたはそれらの時のためにキャストを非表示にすることができます。また、すべてのファクトリタイプを通常の継承の意味で多態的に扱うことができます。しかし、オブジェクトがFactoryと入力されている場合、オブジェクトタイプはFactoryに戻ります。

ここは継承関係を使用しても意味がないかもしれない、これらのクラスが使用されている方法に応じて継承関係

を再検討します。コードの再入力を心配するだけの場合は、代わりにコード生成を調べるとよいでしょう。

+0

可能であれば、過負荷を起こすことなく、2番目のクラスを可能な限り短くしたいと思っていました。あなたの答えははっきりしていて助けになります。ありがとう。コード生成もチェックし、決して使用しません。 – thexebolud

1

問題を簡単にするためにジェネリックを使用する可能性がありますが、ある時点でキャストする必要はありません。たとえば、次のようになります。

Public Class Factory(Of T) 
    Public Function clone() As Factory(Of T) 
     ' Some logic here 
     ' return something 
    End Function 

    Public Function all() As Collections.Generic.List(Of T) 
     ' Some logic here 
     ' return something 
    End Function 
End Class 

Public Class BookFactory 
    Inherits Factory(Of Book) 

End Class 
関連する問題