クラスのメンバーを初期化するためにパラメーターを持つコンストラクターを使用する方が良いですか、それともセッター関数を使用して間接的にそれを行う方が良いですか?これまでのところ、この質問に対する明確な答えは得られませんでした。任意の洞察をいただければ幸いです。
3 に答える
それはほぼ確実にデザインの選択または時にはスタイルの問題です。私はいくつかのことを考えます:
メンバー変数を設定せずにオブジェクトを作成すると、クラスが無効な状態になりますか?その場合、それらのメンバーの有効な値を取得するためにコンストラクターが必要になります。それ以外の場合は、便利なデフォルトを提供できるはずです。
変数の個々のメンバーを設定すると、クラス不変条件に違反しますか?もしそうなら、彼らは彼ら自身のセッターを持つべきではありません。
このクラスのユーザーは、個々のメンバーを変更したいと思う可能性がありますか?もしそうなら、セッターが適切かもしれません。
オブジェクトの個々のメンバーを変更できることは概念的に意味がありますか?
Person
の生年月日を変更できるのは意味がないと私は主張します。Person
ただし、 'の名前を変更することは理にかなっていると主張することができます。場合によります。Person
システム内で名前が変更されたのは別のものだPerson
と思いますか?セッターをグループ化して、より便利にできますか?との代わりに
Rectangle::setX(int)
、Rectangle::setY(int)
もっとRectangle::setPosition(int,int)
意味がありますか?おそらくRectangle::setPosition(Point)
もっと良いです。
いずれにせよ、メンバーのフルセットが個々のセッターとゲッターを通して公開されているクラスは、通常、コードの臭いです。
避けたいことの1つは、完全ではないオブジェクトを持つことです。すべてのパラメーターに適切なデフォルトを指定できる場合は、コンストラクターでの設定をスキップしてもかまいません。そうでない場合は、実際にパラメーターを配置する必要があります。
当然、両方ができない理由はありません。
場合によります。確かに、有効なクラスメンバーがないとオブジェクトが意味をなさない場合は、コンストラクターパラメーターを使用してください。たとえば、スコープ付きスマートポインター、またはofstreamのファイル名などです。
explicit ofstream ( const char * filename, ios_base::openmode mode = ios_base::out );
追加のパラメーターは慎重に使用し、可能な限りデフォルト値を提供してください。
ただし、順序を思い出せなくなるほど、またはこのような危険な混乱の可能性がある場合は、コンストラクターパラメーターをあまり追加しないでください。
Person(std::string firstname, std::string lastname, std::string title, std::string occupation,
std::string address, std::string telephone, int age, std::string creditcard, time_t birthday)