2012-12-29 43 views
5

Có phải nó có trong vb.net để có phương thức xây dựng một đối tượng của bất kỳ lớp dẫn xuất nào trong lớp trầm không? Trong mã này x.Clone sẽ trả về một đối tượng Bar. Là cách duy nhất để dulpicate mã trong cả hai lớp với cả hai loại đối tượng khác nhau.Xây dựng đối tượng của kiểu dẫn xuất trong đối tượng Cơ sở

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 

Trả lời

3

Câu trả lời tùy thuộc vào những gì bạn đang cố gắng thực hiện trong phương pháp nhân bản.

Nếu bạn muốn tạo phiên bản mới của lớp hiện tại mà không thực sự sao chép bất kỳ thuộc tính nào (có vẻ như bạn có thể quan tâm đến việc làm dựa trên mã mẫu và mô tả), thì giải pháp đơn giản là:

Public Class Foo 
    Implements ICloneable 

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

bạn có thể kiểm tra điều này được gọi bằng cách thêm một tin nhắn (hoặc một số loại gỡ lỗi hoặc đầu ra) tại Bar:

Public Class Bar 
    Inherits Foo 

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

End Class 

Nếu bạn có Option Strict On, mà tôi khuyên, các mã trong chính sẽ là:

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

Tuy nhiên, nếu bạn quan tâm đến việc sao chép các giá trị thành viên từ lớp hiện tại, bạn có thể sử dụng MemberwiseClone:

Public Class Foo 
    Implements ICloneable 

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

Tuy nhiên, điều này sẽ chỉ tạo ra một bản sao cạn, sẽ sao chép tài liệu tham khảo, và sẽ không gọi hàm khởi tạo trên Bar. Khi chúng ta sử dụng MemberwiseClone theo cách này, chúng tôi luôn thêm một phương pháp overridable có thể được sử dụng bởi những người thừa kế thực hiện bài-clone dọn dẹp:

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 

Cuối cùng, nếu sao chép cạn hoặc đối phó với sự tham khảo sao chép không phải là để bạn thích, bạn có thể thực hiện một bản sao sâu sử dụng một thủ thuật giá rẻ, nhưng rất hiệu quả: serialization và deserialization sử dụng 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 

Điều này đòi hỏi các lớp học được serializable, nhưng đó là dễ dàng để làm.

+0

+1 nhưng tôi không thích kiểu VB này; mặc dù trình biên dịch không ủy thác nó, bạn nên hội đủ điều kiện các cuộc gọi hàm của bạn với các dấu ngoặc đơn để phân biệt chúng với các truy cập thuộc tính: đó là, viết 'Me.GetType()' thay cho 'Me.GetType', v.v. –

+0

@KonradRudolph: +1. Tôi đồng ý và luôn luôn làm theo điều này trong mã sản xuất, nhưng chỉ cần ném cùng một mẫu nhanh chóng, tôi figured nó sẽ là tốt. –

Các vấn đề liên quan