2

そのため、継承を使用すると、最も特定のクラスで非常に長いコンストラクターを処理していることに常に気づきます。この問題を回避できるパラダイムまたは方法を探しています。ファクトリを使用することも考えましたが、使用した場合でも、ファクトリでコンストラクタを使用する必要があります。その考えに関係なく、コンストラクターのパラメーターの長さを抑えるためにできることはありますか?

例えば:

abstract class DrawableComponent : Component, ITransformable, IScalable, IDrawable, IRotatable

次のようなコンストラクタを持つ子クラスです

DrawableComponent(string Name, int SizeX, int SizeY, int X, int Y, float Rotation) : base(Name) { ... }

では、その子を作りたいとしましょう。物事はより複雑で醜くなるだけです。

class TextBoxComponent : DrawableComponent, IRenderable

コンストラクターは非常に長くなります。

public TextBoxComponent(
    IDrawableUnit Background,
    IDrawableUnit Text,
    string Name,
    int X,
    int Y,
    int SX,
    int SY)
: base(Name, SX,SY,X,Y,0.0f)
{
    this.Background = Background;
    this.Foreground = Foreground;
}

これを要約すると、次のようなことにうんざりしています。

class Blah {Blah(blah)}
class childBlah : Blah {childBlah(blah,blahs,blaha) : base (blah)}
class grandChildBlah : childBlah {grandChildBlah(blah, blahs, blaha, blaht, blauh) : base(blah,blahs,blaha) }
4

4 に答える 4

5

コンストラクターのパラメーター リストが非常に長い場合、1 つのクラスに多くのフィールドが必要ですか? これは、これらのクラスを複数のクラスに分割するか、関連するフィールドのグループを独自のタイプに抽出することを検討する必要があることを示しています。

たとえば、x および y 座標フィールドまたは幅と高さの値:

private double mX;
private double mY;
private double mWidth;
private double mHeight;

実際には、単一の点、ベクトル、または四角形のオブジェクトである必要があります。

private vector mPosition;
private vector mSize;

// or

private rectangle mRegion;

もう 1 つの提案は、継承を減らし、代わりにコンポジションを使用することです。is-a関係の代わりに、 has-a関係を使用します。

あなたの「何とか」の例は次のようになります。

class Blah
{
   Blah(int blah) { ... }
}

class ChildBlah
{
   Blah mBlah;
   ...
   ChildBlah(Blah blah, int blahs, int blaha)
   { mBlah = blah; ... }
}

class GrandChildBlah
{
   ChildBlah mChildBlah;
   ...
   GrandChildBlah(ChildBlah blah, int blaht, int blahu)
   { mChildBlah = blah; ... }
}
于 2012-05-23T22:06:58.627 に答える
2

はい、Builder パターンを使用できます。少なくとも、これにより、コンストラクターへの呼び出しが 1 つのクラスに制限されます。例えば:

VehicleBuilder builder = new VehicleBuilder();
builder.setColor( Color.Green );
builder.setEngineSize( EngineSize.Size1500 );
builder.setWheelSize( 14 );
Vehicle auto = builder.makeVehicle();

別の可能性は、これらのパラメーターの一部をクラスに分割することです。不変オブジェクトを作成している場合でも、防御的なコピーを作成すると、変更可能なパラメーターを渡すことができます。

VehicleParameters parameters = new VehicleParameters();
parameters.setColor( Color.Green );
parameters.setEngineSize( EngineSize.Size1500 );
parameters.setWheelSize( 14 );
Vehicle auto = new Vehicle( parameters );
于 2012-05-23T22:06:38.220 に答える
0

できることがいくつかあります。コンストラクターの連鎖、またはオプションの引数のいずれか。

コンストラクター チェーンとは、基本的に、既定のコンストラクターがあり、追加のパラメーターごとに、または必要に応じてもう 1 つのコンストラクターがあることを意味します。

そのようです:

class Class1
{
    private string name, jobTitle, address;

    public Class1(string name, string title) 
        : this(name, title, "my default address") {}

    public Class1(string name, string jobTitle, string address)
    {
        this.name = name;
        this.jobTitle = jobTitle;
        this.address = address;
    }
}

もう 1 つのオプションは、次のようなオプションのパラメーターです。

class Class1
{
    private string name, jobTitle, address;

    public Class1(string name = "default", string jobTitle = "defaultJob", string address = "defaultAddress")
    {
        this.name = name;
        this.jobTitle = jobTitle;
        this.address = address;
    }
}

必須パラメータは、常にオプション パラメータよりも前に指定する必要があることに注意してください。

于 2012-05-23T22:23:01.527 に答える
0

関心のある属性を保持するキーと値のペアのディクショナリを渡すことで、痛みを和らげることができます。読みやすさと構文を向上させるために、このディクショナリは、ASP.NET MVC のようなライブラリと同様に、匿名クラスから構築できます。多くのメソッド呼び出しに対して。

次に、各レベルで 2 つのコンストラクターを使用します。ディクショナリを取得する保護されたコンストラクターと、匿名オブジェクトを取得するパブリック コンストラクターです。匿名オブジェクト自体は、常にディクショナリに変換された匿名オブジェクトで保護されたコンストラクターを呼び出します。

public class Class1 {
  public Class1(object args): this(new RouteValueDictionary(args)) {}

  protected Class1(RouteValueDictionary args) {
    // retrieve any property you need here from args
  }
}

public class Class2: Class1 {
  public Class2(object args): this(new RouteValueDictionary(args)) {}

  protected Class2(RouteValueDictionary args): base(args) {
    // retrieve any property specific to Class2 from args
  }
}

// etc.

これを次のように使用します。

new Class2(new {
    X: 10,
    Y: 20,
    Name: "instance"
  });

利点は、渡された引数の数に関係なく、これにより優れた構文が得られることです。また、引数を省略したり、コンストラクターの非常に動的な「オーバーロード」を作成したりすることもできます。このアプローチの主な問題は、コンストラクターに何を渡す必要があるかをコンパイル時にコンパイラーが通知できないことです (たとえば、静的解析の利点の一部が失われます)。

注:RouteValueDictionaryここで解析に使用される は、MVC プロジェクトの一部ではなく、System.Web アセンブリの一部であるため、完全な .NET フレームワークが展開されているすべての場所ですぐに利用できます。匿名型の抽出を効率的に処理します。通常は、自分で手動で反映するよりも優れています。

于 2012-05-23T23:07:53.113 に答える