2

私は、.NET で継承/インターフェイス/実装をもう少しうまく理解しようとしています。

次のように定義されたクラスがあります(一種):

Public Class Sheet
    Property Name As String
    Property Steps As List(Of [Step])
End Class

問題は、[Step] は単なる仮想の基底クラスです。[Step] には 5 つの異なる具体的な実装があります。問題をもう少し複雑にするために、[Step] には 3 つの DIRECT 実装があり、そのうち 2 つは仮想です。これらの 2 つのそれぞれには、[Step] を具体的に実装する 2 つのサブクラスがあります。

それで、これがどのように見えるかです:

                          Step
         |-----------------|-----------------|
         |                 |                 |
     SubStepA          SubStepB          SubStepC
    |----|----|                         |----|----|
    |         |                         |         |
SubStepAA SubStepAB                 SubStepCA SubStepCB

したがって、SubStepB、SubStepAA、SubStepAB、SubStepCA、および SubStepCB が具体的な実装です。

Clone() など、ANY Step に実行してもらいたいことがいくつかあります。

そこで、Step で次のように宣言してみました。

Public MustOverride Function Clone() As Step

問題は、SubStepAA でそれを実装しようとすると、次のように宣言できないことです。

Public Overrides Function Clone() As SubStepAA

これを行うと、戻り値の型が同じではないというエラーが表示されます。

これに対する解決策は、具体的なサブクラスを複製するたびに DirectCast 呼び出しを使用することですか? それは奇妙で満足できないようです。それも間違っているようです。つまり、SubStepAA オブジェクトのクローンを作成した場合、SubStepAA タイプのオブジェクトを取得したいと考えています。

これを行う方法があるはずですよね?つまり、各クラスを必要な方法で宣言するだけでよいと思いますが、(本質的に) 同じ方法で (本質的に) 同じように動作する 5 つの異なる Clone() メソッドを作成する必要があるのも間違っているようです (ディープ コピーの作成参照されたオブジェクトの)。

Interface宣言の使用を検討しましたが、同じタイプの不一致エラーが発生しているようです。

基本的なものが足りないと教えてください!

ありがとう!

余談ですが、私はいくつかの読書をしており、オブジェクトのディープコピーを行うためのより最適化された方法があるかもしれないことを認識しています (たとえば、シリアライゼーション/デシリアライゼーションを介して)。別のアプローチを使用してオブジェクトを複製します。

4

1 に答える 1

2

これはまさにあなたが望んでいるものではないかもしれませんが、次のようにジェネリック基本型を使用することですべての要件を満たすことができます。

Public MustInherit Class [Step](Of T)
    Public MustOverride Function Clone() As T
End Class

Public Class StepA
    Inherits [Step](Of StepA)

    Public Overrides Function Clone() As StepA
        ' ...
    End Function
End Class

Stepただし、すべての派生型に使用できる共通の基本クラスはありません。たとえば、次のようなことを行う方法はありません。

Dim s As [Step] = New StepA()  'Won't work because there is no Step type, only a generic Step(T) type
Dim c As [Step] = s.Clone()

ただし、そのような共通の基本型が必要な場合は、追加の複雑さはありますが、そのようなことを行うことができます。

Public Interface ICloneable(Of T)
    Function Clone() As T
End Interface

Public MustInherit Class [Step]
    Implements ICloneable(Of [Step])

    Public MustOverride Function CloneBase() As [Step] Implements ICloneable(Of [Step]).Clone
End Class

Public MustInherit Class [Step](Of T As [Step])
    Inherits [Step]

    Implements ICloneable(Of T)

    Public Overrides Function CloneBase() As [Step]
        Return Clone()
    End Function

    Public MustOverride Function Clone() As T Implements ICloneable(Of T).Clone
End Class

Public Class StepA
    Inherits [Step](Of StepA)

    Public Overrides Function Clone() As StepA
        ' ...
    End Function
End Class

そのようにした場合、各具体的なオブジェクトを としてStep(T)または としてキャストできる追加の抽象化レイヤーが得られますStep。たとえば、次のようにできます。

Dim s As [Step] = New StepA()
Dim c As [Step] = s.CloneBase()

しかしもちろん、これには疑問がつきものです。より単純な 2 つの解決策は、各派生クラスで独立してインターフェイスを実装する (したがって、基本クラスからクローンを呼び出す機能を放棄する) か、最初のアイデアを使用して、Cloneメソッドが常に基本型を返すようにすることです。

于 2012-12-28T16:25:26.353 に答える