2012-12-29 115 views
5

在vb.net中可以使用構造貝司類中任何派生類的對象的方法嗎? 在這段代碼中,x.Clone應該返回一個Bar對象。 是使用兩種不同的對象類型來強化這兩個類中的代碼的唯一方法。在基礎對象中構造派生類型的對象

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 

回答

3

答案具體取決於您在克隆方法中想要完成的工作。

如果你想在沒有實際複製任何屬性的情況下創建當前類的新實例(這聽起來像你可能有興趣根據示例代碼和描述做),那麼簡單的解決方案是:

Public Class Foo 
    Implements ICloneable 

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

您可以測試,這是所謂的加入在酒吧消息(或某種調試或輸出的):

Public Class Bar 
    Inherits Foo 

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

End Class 

如果你有Option Strict On,我強烈建議,該代碼在主將是:

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

不過,如果你有興趣的複製從當前類的成員的值,可以使用MemberwiseClone

Public Class Foo 
    Implements ICloneable 

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

然而,這隻會造成一個淺拷貝,將複製引用,將不會調用Bar上的構造函數。當我們以這種方式使用MemberwiseClone,我們隨時補充,可以通過繼承來執行克隆後的清理可重寫的方法:

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 

最後,如果淺複製或處理複製引用對您並不順心,您可以執行使用價格便宜,但非常有效的一招了深刻的副本:序列化和反序列化使用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 

這就要求類可序列化,但是這是很容易做到。

+0

+1但我不喜歡VB的這種風格;即使編譯器沒有強制它,你應該用括號來限定你的函數調用,以區別於屬性訪問:也就是說,寫'Me.GetType()'而不是'Me.GetType'等。 –

+0

@KonradRudolph:Thanks for +1。我同意並始終在生產代碼中遵循這一點,但只是將一個快速樣本放在一起,我認爲它會很好。 –

相關問題