0

言語設計者が意図したデフォルトの慣行と、後でそれらの慣習から逸脱したとしても、言語の改善を目標とするデフォルトの慣行を知ることは常に役立つと思います。Scala では、すべてのフィールドは、宣言されているクラスのコンストラクターで初期化する必要があります。これは重大な制限です。2 次コンストラクターも制限されています。コンストラクター内の一時変数は、コンストラクターの本体が乱雑に見える可能性がある不要なフィールドを回避するために、内部メソッドまたはクロージャーに配置する必要があります。これはすべて、コンストラクタ本体の使用に不利です。スーパークラスから抽象変数に代入する場合でも必要なオーバーライド val/var 構文は、構築のために派生クラスを使用する利点の一部を取り除きます。

コンパニオン オブジェクトは、そのクラスのすべてのフィールドにアクセスできます。ただし、クラスのコンストラクターですべてのフィールドを初期化する必要があるため、構築の場合、これは最初に現れる可能性があるという利点ではありません。そのため、オブジェクト内のメソッドを使用してクラス変数の処理を行い、クラス内の不変コレクションごとに一時的な可変コレクションを作成し、listbuffer をデフォルトにして、すべての値とコレクションを実体のないコンストラクタ。ファクトリは任意のオブジェクトまたはクラスに含めることができますが、特に理由がない限り、コンパニオン オブジェクトに含めることもできます。オブジェクトは型パラメータを取ることができませんが、ファクトリ メソッドは必要に応じて取ることができます。そしてもちろん、準コンストラクターが必要な数のファクトリ メソッドを持つことができ、一般的なアルゴリズムを再利用できます。

これは正しいです?

例の要求に応えて、C# から Scala に移植する過程にあるコンストラクターを次に示します。Scala では複数の型パラメーターがなくなっていることに注意してください。

public class GridC : GridBase<HexC, SideC, UnitC, ISegC>
{        
    public Geometry<HexC, SideC, UnitC, ISegC> geomC { get; private set; }        

    internal GridC(Scen scen, int gridNum, int xDim, int yDim, int xOff, int yOff, Terr terr = Terr.Plain):
        base(gridNum, scen, 10.0)
    {            
        this.geomC = scen.geomC;
        xIntLeft = xOff + 1;
        yIntBottom = yOff;
        xIntRight = xDim * 2 + 1 + xOff;
        yIntTop = yDim * 2 + 2 + yOff;            
        Coodg hexCoodg;
        for (int x = xOff; x < xDim * 2 + xOff; x += 2)
        {
            for (int y = yOff; y < yDim * 2 + yOff; y += 2)
            {
                if (x % 4 == y % 4)
                {
                    hexCoodg = new Coodg(num, x + 2, y + 2);                         
                    HexC hexC = scen.hexCs.NewHexC(hexCoodg);
                    SideC sideC;
                    MiscStrat.sixDirn.ForEach(i =>
                        {
                            Coodg sideCoodg = hexCoodg + Cood.DirnTrans(i);
                            sideC = sides[sideCoodg];
                            if (sideC == null)
                                scen.sideCs.NewSide(hexC, i);                                
                            else
                                scen.sideCs.SetHex2(sideC, hexC, i);
                        });                                                                         
                }
            }
        }
    }

上記のサブクラスは、構築に関連する部分を示すためだけに編集された次の基本クラスのコンストラクターを提供するために純粋に作成されています。

public class GridBase<HexT, SideT, UnitT, SegT> : IGridBase
    where HexT : Hex where SideT : Side where UnitT : Unit where SegT : ISeg
{
    public int num { get; private set; }
    int IGridBase.num { get { return num; } }
    IListsGeom<HexT, SideT, UnitT> iLists;
    public HexList<HexT> hexs { get { return iLists.hexs; } }
    public SideList<SideT> sides { get { return iLists.sides; } }
    public Geometry<HexT, SideT, UnitT, SegT> geom { get; private set; }        
    public int xIntLeft { get; protected set; }
    public int xIntRight { get; protected set; }
    public int yIntBottom { get; internal set; }
    public int yIntTop { get; internal set; }
    public double scale { get; private set; }        

    protected GridBase(int num, IListsGeom<HexT, SideT, UnitT> iLists, double scale)
    {
        this.num = num;
        this.iLists = iLists;
        this.scale = scale;
    }
}

コンストラクターは、単純な均一な Hex グリッドを作成します。完全に異なるアルゴリズムを使用する他のコンストラクターが必要であり、関連するがより複雑なアルゴリズムを必要とする他のコンストラクターが作成されます。私は専門家ではありませんが、私の印象では、ファクトリは C# ではあまり使用されていません。

4

3 に答える 3

2

あなたの質問を理解できれば、複雑な構築方法を必要とするものには、コンパニオン オブジェクトでそれをサポートするメソッドを適用する必要があると言えます。しかし、私は彼らがそのような複雑な建設要件を持っていることを懸念しています.

于 2012-05-26T17:55:01.377 に答える
1

一般に、通常、(基本)クラスのコンパニオンオブジェクトのメソッドを介して、このような複雑な構造を提供します。これにより、初期化コードと構築後の使用コードが明確に分離されます。

また、不変のデータがあると、より小さく、より焦点を絞った懸念事項を設計するのに役立つ場合があります。たとえば、独自のクラス(または必要に応じてタプル)に分離できるボックス(左、右、上、下)があります。

于 2012-05-26T22:00:10.820 に答える
1

クラスのコンストラクターですべてのフィールドを初期化する必要があるというあなたの声明について:これに対処するには2つの方法があります。

  1. クラスのコンストラクターで、より複雑なフィールドをデフォルト値に設定します。val a: Int = _
  2. コンパニオン オブジェクトの apply メソッドで計算を行い、コンストラクターですべてのフィールドを初期化します (つまり、事前に計算されたすべての値をコンストラクターに渡します)。

個人的には、オブジェクトが構築後に意味的に完全であることを保証する 2. を好みます。

于 2012-05-27T09:25:38.073 に答える