2

すべて同じShapeクラスから継承するいくつかのクラスがあります。新しい形状を作成するときは、ランダムな形状にしたいと考えています。私が考えた方法は、すべてのコンストラクターへのリンクを保持するリストを作成することです。新しい形状を作成する必要がある場合は、リストからランダムなコンストラクターを取得し、それを使用して形状を構築します。次の方法でリストを作成しようとしましたが、エラーが発生します。

List<Action> constList = new List<Action>();
constList.Add(SShape());
constList.Add(OShape());
constList.Add(LShape());

コンストラクターは次のShapeように定義されます。

class Shape
{
    public Shape(PlayGrid grid, Color color)
    {
        ...
    }
    ...
}

そして、各サブシェイプのコンストラクターは次のように定義されます:

class IShape : Shape
{
    public IShape(PlayGrid grid, Color color) : base(grid, color)
    {
    ...
    }
...
}

リストを構築する正しい方法と、リストからコンストラクターを使用する方法は何ですか?

請負業者は、異なる形状間で変化するパラメーターも取得する必要があります。

4

6 に答える 6

5

この概念は機能します。デリゲートを生成するための構文が間違っているだけで、 ではFunc<PlayGrid, Color, Shape>なくAction:

var constList = new List<Func<PlayGrid, Color, Shape>>();
constList.Add((pg, c) => new SShape(pg, c));

PlayGrid playgrid = /* however you get this */;
Color color = /* however you get this */;
var shape = constList[randomIdx](playgrid, color);
于 2013-03-22T12:25:54.980 に答える
2

次のようなことができます。

public class ShapeFactory()
{
   //list of shape constructor functions
   private List<Func<Shape>> constructors;

   //static initalizaton of the constructor list
   static ShapeFactory()
   {
      constructors = new List<Func<Shape>>();
      constructors.Add( () => new OShape());
      constructors.Add( () => new SShape());
      constructors.Add( () => new LShape());
      ....
   }

   public static Shape CreateRandomShape()
   {
       int index = ...get random index somehow...
       return constructors[index]();
   }
}

そしてそれをコードで使用します

Shape randomShape = ShapeFactory.CreateRandomShape();
于 2013-03-22T12:31:55.817 に答える
0

これはあなたが始めたことの続きです。Reflectionを使用してコンストラクターを呼び出します。最初のリストはタイプのリストであり、アクションのリストではありません。

class Program
    {
        static void Main(string[] args)
        {


            //register the types
            List<Type> types = new List<Type>() { typeof(OShape), typeof(PShape), typeof(RShape) };

            // randomly select one
            Type type = types[1];

            // invoke the ctor
            ConstructorInfo ctor = type.GetConstructor(/*optional param for ctor, none in this case*/ new Type[] {} );
            object instance = ctor.Invoke(new object[] {});

            // you can safely cast to Shape
            Shape shape = (Shape)instance; //this is a PShape!

        }
    }

    class Shape
    {
    }

    class OShape : Shape
    {
    }

    class PShape : Shape
    {
    }

    class RShape : Shape
    {
    }
}

次に考えるべきことは、Shapeのサブタイプがパラメーターを受け取ることを許可する方法です。ファクトリパターン、つまり他のオブジェクトの作成方法を知っているオブジェクトが必要であり、たとえば文字列に基づいて作成します。

Shape s = Factory.GetShape("OShape", new[] object {4});

この質問をチェックしてください。

于 2013-03-22T12:35:03.760 に答える
0

すべての形状に対してインターフェイス(おそらく「IShape」)を作成し、ファクトリを使用してそれらをインスタンス化する必要があると思います (その時点で、IShape インターフェイスを実装する任意の型をランダムにインスタンス化できます)。

于 2013-03-22T12:26:02.993 に答える
0

この方法でランダム オブジェクトを作成する責任は、オブジェクト自体の動作にあるべきではありません。これを管理するためのファクトリを作成することをお勧めします。ファクトリは、コンストラクター呼び出しのリストを生成 (またはオブジェクトを事前にキャッシュ) し、そのうちの 1 つをその create メソッドで提供できます。ファクトリは、オブジェクトを作成するために呼び出すアクションではなく、構築されたオブジェクト (おそらく IShape などのインターフェイスとして) を返す必要があります。そうすれば、ファクトリが依存関係を注入したり、他の値を設定したりする必要がある場合、それを実行してオブジェクトの構築を管理できます。

また、それが .NET Action クラスの場合、Shape クラスはそれを継承していないと思いますが、「エラーが発生する」という質問からは不明です。

基本クラスに GetRandomShape() メソッドがあることについてのコメントがあります。これは、基本クラスがそのサブクラスを認識しており、そのサブクラスに依存しており、OO 設計の慣行に違反しているため、望ましくありません。

于 2013-03-22T12:26:44.270 に答える
0

クラスのタイプをリストに保存しActivator.CreateInstance(Type)、新しいインスタンスを取得するために使用できます。

または、Shape 型のリストを作成し、すべてのクラスのインスタンスを 1 つ追加し、.Clone()メソッドを使用して新しいインスタンスを取得します。

または、ファクトリ パターンを実装します。

于 2013-03-22T12:27:52.180 に答える