Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructing object of derived type in Base object

Tags:

.net

class

vb.net

Is it possable in vb.net to have a method that constructs an object of any derived class in the bass class? In this code x.Clone should return a Bar object. Is the only way to dulpicate the code in both class's with both different object types.

Module Module1

    Sub Main()
        Dim x As New Bar
        Dim y As Bar = x.Clone
    End Sub

End Module

Public Class Foo
    Implements ICloneable
    Public Function Clone() As Object Implements System.ICloneable.Clone
        Clone = Me.new() 'fails to compile as not in a constructor
        Clone = new Foo 'constructs a new foo in the derived class
    End Function
End Class

Public Class Bar
    Inherits Foo
    'additional implementation
    'but no addition fields
End Class
like image 380
user1937198 Avatar asked Oct 21 '22 21:10

user1937198


1 Answers

The answer depends on specifically what you are trying to accomplish in the cloning method.

If you want to create a new instance of the current class without actually copying any of the properties (which is sounds like you may be interested in doing based on the sample code and description), then the simple solution is:

Public Class Foo
    Implements ICloneable

    Public Function Clone() As Object Implements System.ICloneable.Clone
        Return Activator.CreateInstance(Me.GetType)
    End Function
End Class

You can test that this is called by adding a message (or some sort of debug or output) in Bar:

Public Class Bar
    Inherits Foo

    Public Sub New()
        MsgBox("Test")
    End Sub

End Class

If you have Option Strict On, which I strongly recommend, the code in main would be:

Sub Main()
    Dim x As New Bar
    Dim y As Bar = DirectCast(x.Clone, Bar)
End Sub

However, if you are interested in copying the member values from the current class, you can use MemberwiseClone:

Public Class Foo
    Implements ICloneable

    Public Function Clone() As Object Implements System.ICloneable.Clone
        Return Me.MemberwiseClone
    End Function
End Class

However, this will only create a shallow copy, will copy references, and will not invoke the constructor on Bar. When we use MemberwiseClone in this manner, we always add an overridable method that can be used by inheritors to perform post-clone cleanup:

Public Class Foo
    Implements ICloneable

    Public Function Clone() As Object Implements System.ICloneable.Clone
        Dim oObject As Foo

        oObject = DirectCast(Me.MemberwiseClone, Foo)
        oObject.PostCloneCleanup()

        Return oObject
    End Function

    Protected Overridable Sub PostCloneCleanup()

    End Sub
End Class

Public Class Bar
    Inherits Foo

    Public Sub New()
        MsgBox("Test")
    End Sub

    Protected Overrides Sub PostCloneCleanup()
        MsgBox("PostCloneCleanup")
    End Sub

End Class

Finally, if shallow copying or dealing with copied references is not to you liking, you can perform a deep copy using a cheap, but very effective trick: serialization and deserialization using the BinaryFormmater:

Public Function CreateDeepCopy(Of T)(ByVal oRecord As T) As T

    If oRecord Is Nothing Then
        Return Nothing
    End If

    If Not oRecord.GetType.IsSerializable Then
        Throw New ArgumentException(oRecord.GetType.ToString & " is not serializable")
    End If

    Dim oFormatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

    Using oStream As IO.MemoryStream = New IO.MemoryStream
        oFormatter.Serialize(oStream, oRecord)
        oStream.Position = 0
        Return DirectCast(oFormatter.Deserialize(oStream), T)
    End Using
End Function

This requires that the classes be serializable, but that is easy to do.

like image 146
competent_tech Avatar answered Oct 27 '22 09:10

competent_tech