Thursday, December 06, 2007

Neat Pattern for Cloning with Inheritance

For once I've come across an MSDN forum post which exactly solves a problem I had. I'm not having the same problem as the person who asked the question, but the solution given was spot on for me.

Suppose you have two classes, SuperClass and SubClass, where SubClass inherits from SuperClass. If I want to create a deep copy of SubClass I should really implement a Copy method in SuperClass, and override that in SubClass.

But if I do that I can't really use the Copy method in SuperClass, because I can't cast a SuperClass to a SubClass.

The solution (as described in the above post: I can claim zero credit for this neat pattern), is to instead create a CopyFrom method, in which a SuperClass can be populated from another SuperClass. Then in the SuperClass's Copy method I create a new SuperClass, and call the CopyFrom method on it, passing in "this" (or "Me", if in VB.Net).

Then SubClass can override CopyFrom and call into the base method, adding any further properties that SubClass has. SubClass then overrides the Copy method, creates a new SubClass, and calls CopyFrom before returning it.

This is the code from the post above (credit to "nobugz"):


Class A
Private DataA As String = "Data-A"
Public Sub New()
End Sub
Public Overridable Sub CopyFrom(ByVal obj As A)
Me.DataA = obj.DataA
End Sub
Public Overridable Function Clone() As A
Dim NewA As New A
NewA.CopyFrom(Me)
Return NewA
End Function
End Class

Class B
Inherits A
Private DataB As String = "Data-B"
Public Sub New()
End Sub
Public Overrides Sub CopyFrom(ByVal obj As A)
obj.CopyFrom(Me)
Me.DataB = CType(obj, B).DataB
End Sub
Public Overrides Function Clone() As A
Dim obj As B = New B
obj.CopyFrom(Me)
Return obj
End Function
End Class

1 comment:

Mark S said...

My understanding of VB.net is nothing like that of my C#, but isn't the call to CType(obj, B) effectively performing a cast from type A to type B, from super to sub?

From my efforts, a C# version of this is not possible.