0

質問したばかりの質問を再投稿していますが、混乱を引き起こしていると思うので、より簡潔な方法でこの質問を再質問したいと思います。

基本クラスはRoomObjectです。RoomObjectから継承するBedとTableの2つのサブクラスがあります。

RoomObject型の変数currentObjectがありますが、実際にはBedまたはTableのインスタンスを保持します(RoomObjectがそれ自体でインスタンス化されることはありません)。

フルタイプを知らなくても、currentObjectのクローンを作成するにはどうすればよいですか?

つまり、currentObjectがBedの場合、次を使用してBedのクローンを作成します。

currentObject = new Bed(currentObject); 

currentObjectがテーブルの場合、使用したい

currentObject = new Table(currentObject);

Activator.CreateInstance(currentObject.GetType())を呼び出してリフレクションを使用し、必要な属性をコピーすることもできますが、これは面倒なようです。

4

4 に答える 4

6

仮想コンストラクターまたはクローン作成メソッドと呼ばれるパターンを使用する必要があります。

RoomObject現在のオブジェクトのコピーを返す仮想メソッドを追加します。

abstract RoomObject Clone();

ここで、このメソッドをに実装して、をBed返しnew Bed(...)、にを実装します。のコンストラクターに必要なパラメーターを渡し、現在のオブジェクトにあるものをコピーします。Tablenew Table(...)BedTable

.NETには、ICloneableこのパターンを実装するために一般的に使用されるインターフェイスがあります。このアプローチの小さな欠点は、ではなく、Cloneを返さなければならないことです。したがって、必要な場合は、それをキャストする必要があります。objectRoomObjectRoomObject

于 2012-12-12T15:14:41.147 に答える
1

これは、リフレクションの最も優れた点の1つです。クライアントコードがオブジェクトのタイプを認識していなくても、オブジェクトを作成できることです。場合によっては、コードが乱雑になったり、速度が低下したりすることもありますが、正しく使用すると、コードがはるかに管理しやすくなります。

たとえば、ファクトリパターンを見て、Reflectionここでもそれを実装する方法を見てください。

于 2012-12-12T15:16:59.903 に答える
1

1つの解決策は、すべてのオブジェクトにICloneableインターフェイスを実装することだと思います。サンプルコードは次のとおりです。

class RoomObject : ICloneable
{
    public abstract object Clone();
}

class Bed : ICloneable
{
    public override object Clone()
    {
        return new Bed();
    }
}

class Table : ICloneable
{
    public override object Clone()
    {
        return new Table();
    }
}

class Program
{
    public static void Main(String[] args)
    {
        RoomObject ro = /* from some other places*/
        RoomObject newOne = ro.Clone() as RoomObject;  /* here's what you what */
    }
}
于 2012-12-12T15:20:59.727 に答える
1

その代わりに、ICloneable他の人が回答で述べたように、.NETFrameworkにすぐに使用できるインターフェイスを実装します。

ICloneable.Clone()メソッドはを返すので、これも実装objectするカスタムはどうでしょうか。ICloneable<T>ICloneable

public interface ICloneable<T> : ICloneable
    where T : class
{
    T TypedClone();
}

public class MyCloneableObject : ICloneable<MyCloneableObject>
{
     public string Some { get; set; }

     public object Clone()
     {
         MyCloneableObject clone = new MyCloneableObject { Some = this.Some };
     }

     public MyCloneableObject TypedClone()
     {
          return (MyCloneableObject)Clone();
     }
}

後で、あなたのコードで...

MyCloneableObject some = new MyCloneableObject();

if(some is ICloneable<MyCloneableObject>)
{
    MyCloneableObject myClone = some.TypedClone();

    // .. or the standard `Clone()`:
    myClone = (MyCloneableObject)some.Clone();
}

クローン可能オブジェクトは実装を受け入れる可能性のある他のライブラリで動作するため、組み込みインターフェイスとカスタムインターフェイスの両方を実装することをお勧めしますICloneable

最後に、リフレクションを使用するのではなく、このケースを設計時に解決する必要があります。志望者を含むライブラリを変更できない場合は、リフレクションを使用する必要があると私は主張しますICloneable

于 2012-12-12T15:33:14.410 に答える