2012-12-29 8 views
5

vb.netでは、ベースクラスの任意の派生クラスのオブジェクトを作成するメソッドを使用できますか? このコードでは、x.CloneはBarオブジェクトを返す必要があります。 両方のクラスの両方のオブジェクトタイプでコードを唯一の方法で扱うことができます。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 

答えて

3

答えは、具体的にクローニング方法で達成しようとしているものによって異なります。

実際のプロパティをコピーせずに現在のクラスの新しいインスタンスを作成する場合(サンプルコードと説明に基づいて行うことに興味があるような音です)、簡単な解決策は次のとおりです。

Public Class Bar 
    Inherits Foo 

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

End Class 

あなたは私を強くお勧めしますOption Strict Onを、持っている場合は、メインのコードを:あなたがバーで、これはメッセージ(またはデバッグまたは出力のいくつかの並べ替え)を加えることによって呼び出されることをテストすることができ

Public Class Foo 
    Implements ICloneable 

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

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のコンストラクタは呼び出されません。浅いコピーやコピーの参照を扱うが好きあなたにない場合は、最後に

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 

、:私たちは、このようにMemberwiseCloneを使用すると、私たちは常にクローン後のクリーンアップを実行するために相続で使用することができますオーバーライドメソッドを追加しますあなたは安いが、非常に効果的なトリックを使って深いコピーを実行することができます。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:ありがとう+1。私はこれに同意し、常にこれをプロダクトコードに従いますが、サンプルをまとめて投げるだけで、うまくいくと思いました。 –

関連する問題