これは、不変クラスの例を使用して説明されている問題です。書籍には、少なくとも1つのタイトルとISBNが必要です。
_public class Book
{
private readonly string _title;
private readonly int? _isbn;
public Book(string title)
: this(title, null, true)
{
... throw exception if title is null
}
public Book(int isbn)
: this(null, isbn, true)
{
... throw exception if isbn < 1
}
public Book(string title, int isbn)
: this(title, isbn, true)
{
... throw exception if title is null
... throw exception if isbn < 1
}
private Book(string title, int? isbn, bool privateConstructor = true)
{
_title = title;
_isbn = isbn;
... more work (beyond the scope of this example)
}
... public properties, etc.
}
_
privateConstructor
ブール値を参照してください? public Book(string, int)
とprivateBook(string, int?)
を区別するためにそれを投入する必要がありました。無関係なパラメーターはプライベートコンストラクターにあるため、これはかなり無害ですが、その使用は私には臭いようです。プライベートコンストラクターのパラメーターを並べ替えることは機能しますが、コンストラクターの初期化子が直感的ではないように見えます(私の実際の作業では、2つ以上のパラメーターが機能しています)。より良い方法は何ですか?
これは、オプションのパラメーターを持つC#のように見えます。
パブリックコンストラクターですでに例外をスローしているので、プライベートコンストラクターを除くすべてのコンストラクターを省略できます。公開し、title
をオプションにし、ブールパラメータを削除し、呼び出し元に名前付きパラメータを使用させます。
もう1つできることは、プライベートコンストラクターを代わりに通常のメソッド呼び出しにして、別の名前を付けることです。そうすれば、明確にするためにboolパラメーターは必要ありません。
実際には別の方法はありません。
コンストラクターには常に事前に定義された名前(Pythonのように__init__
のようなもの、またはC++/Java/C#のようにクラス名)があるため、2つのコンストラクターを区別するために変更することはできません。つまり、引数リストのみを使用してさまざまなオーバーロードを作成できます。
パブリックコンストラクターの署名と互換性のある署名が必要な別の(プライベート)コンストラクターに作業を委任する場合は、基本的に3つのオプションがあります。
これらのオプションはどちらも本当にエレガントではないので、最も醜いものではないケースバイケースで決定する必要があります。
プライベートコンストラクターを削除し、最後のパブリックコンストラクターでロジックを実行します。
public class Book
{
private readonly string _title;
private readonly int? _isbn;
public Book(string title)
: this(title, 0)
{
}
public Book(int isbn)
: this(null, isbn)
{
}
public Book(string title, int isbn)
{
... throw exception if title is null AND isbn < 1
... throw exception if isbn < 0
_title = title;
_isbn = isbn > 1 ? isbn : null;
... more work (beyond the scope of this example)
}
}
0を使用して、ISBNが指定されていないことを示します。または、初期値0はISBNがないことを示すため、_isbn
をnull許容にしない方がよい場合があります。そう:
public class Book
{
private readonly string _title;
private readonly int _isbn;
public Book(string title)
: this(title, 0)
{
}
public Book(int isbn)
: this(null, isbn)
{
}
public Book(string title, int isbn)
{
... throw exception if title is null AND isbn < 1
... throw exception if isbn < 0
_title = title;
_isbn = isbn;
... more work (beyond the scope of this example)
}
}
読みやすさの点で優れています。
静的メソッド(createFromTitle
やcreateFromISBN
など)+プライベートconstructructorを使用できない理由はありますか?これらの静的メソッドをコンストラクターとして使用するだけです。