2012-12-29 8 views
5

Czy w wersji vb.net można uzyskać metodę konstruującą obiekt dowolnej klasy pochodnej w klasie basowej? W tym kodzie x.Clone powinien zwrócić obiekt Bar. Jest to jedyny sposób na dulpikację kodu w obu klasach dla obu typów obiektów.Konstruowanie obiektu typu pochodnego w obiekcie Base

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 

Odpowiedz

3

Odpowiedź zależy od konkretnie, co próbujesz osiągnąć w metodzie klonowania.

Jeśli chcesz utworzyć nową instancję bieżącej klasy bez faktycznego kopiowania żadnej z właściwości (co brzmi tak, jakbyś był zainteresowany zrobieniem na podstawie przykładowego kodu i opisu), to proste rozwiązanie to:

Public Class Foo 
    Implements ICloneable 

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

można przetestować, że nazywa się to poprzez dodanie wiadomość (albo jakiś debug lub wyjście) w Bar:

Public Class Bar 
    Inherits Foo 

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

End Class 

Jeśli masz Option Strict On, który gorąco polecam, kod w głównym będzie:

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

Jednakże, jeśli jesteś zainteresowany kopiowanie wartości członkowskich z bieżącej klasy, można użyć MemberwiseClone:

Public Class Foo 
    Implements ICloneable 

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

Jednak ta stworzy tylko płytką kopię będzie skopiować odniesienia i nie wywoła konstruktora na pasku. Gdy używamy MemberwiseClone w ten sposób możemy zawsze dodać przeciążać metody, które mogą być używane przez spadkobierców wykonać porządki po Klon:

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 

Wreszcie, jeśli płytkie kopiowanie lub czynienia ze skopiowanych odniesienia nie ma Cię lubić, można wykonać głęboką kopię używając tani, ale bardzo skuteczny trik: serializacji i deserializacji za pomocą 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 

wymaga to zajęcia być możliwy do serializacji, ale to jest łatwe do zrobienia.

+0

+1 ale nie podoba mi się ten styl VB; mimo że kompilator tego nie upoważnia, powinieneś zakwalifikować swoje wywołania funkcji za pomocą nawiasów, aby odróżnić je od dostępu do właściwości: to, wpisz 'Me.GetType()' zamiast 'Me.GetType' itd. –

+0

@KonradRudolph: Dzięki za +1. Zgadzam się i zawsze podążam za tym w kodzie produkcyjnym, ale po prostu wyrzuciłem razem szybką próbkę, uznałem, że będzie w porządku. –

Powiązane problemy