オブジェクトは常に有効な状態でなければなりません。これは、オブジェクトが常に動作 (メソッド) し、意味のある情報 (メンバー変数) を含むことを意味します。コンストラクターの目的は、オブジェクトを有効な状態で作成することです。
値オブジェクトを考慮して、コンストラクターは、オブジェクトが意味を成すように最小数の引数を取る必要があります。たとえば、RGB 値オブジェクトがある場合、赤が文字列 "monkey"、緑が NULL、青が配列である場合、アプリケーションで意味があるでしょうか?
final class RGB {
$r, $g, $b;
}
$mycolor = new RGB;
// NULL, what value of red is that supposed to be?
var_dump($mycolor->r);
// We are free to set these values too, even though they do not make sense.
$mycolor->r = 'monkey';
$mycolor->g = NULL;
$mycolor->b = array('foo', 'bar');
それがまさにこのオブジェクトが実現できることです。$mycolor は、有効な状態にないオブジェクトを参照しています。RGB オブジェクトが常に赤、青、緑の 3 つの値を持ち、それらがすべて 0 ~ 255 の数値であることを確認するにはどうすればよいでしょうか?
final class RGB {
private $r;
private $g;
private $b;
public function __construct($r, $g, $b) {
// are our arguments numbers?
if (!is_numeric($r)) {
throw new Exception('Value of red must be a number');
}
if (!is_numeric($g)) {
throw new Exception('Value of green must be a number');
}
if (!is_numeric($b)) {
throw new Exception('Value of blue must be a number');
}
// are our arguments within range 0-255?
if ($r < 0 || $r > 255) {
throw new Exception('Value of red must be 0-255');
}
if ($g < 0 || $g > 255) {
throw new Exception('Value of green must be 0-255');
}
if ($b < 0 || $b > 255) {
throw new Exception('Value of blue must be 0-255');
}
// our arguments are fine.
$this->r = $r;
$this->g = $g;
$this->b = $b;
}
//*// Canadian support
public function getColour() {
return $this->getColor();
}
public function getColor() {
return array($this->r, $this->g, $this->b);
}
}
$mycolor = new RGB; // error! missing three arguments
$mycolor->r = 'monkey'; // error! this field is private
// exception! the constructor complains about our values not being numbers
$mycolor2 = new RGB('monkey', NULL, array('foo', 'bar'));
// exception! the constructor complains our numbers are not in range
$mycolor3 = new RGB(300, 256, -10);
$mycolor4 = new RGB(255, 0, 0); // ahh... a nice shade of red
var_dump($mycolor4->getColor()); // we can read it out later when we need to
コンストラクターが 3 つの引数を必要とし、3 つすべてが 0 から 255 の間の数値でない限り例外をスローする場合、常に適切な値でメンバー変数を定義することになります。
赤、青、および緑のメンバー変数がプライベートであることも確認する必要があります。そうでなければ、誰でも好きなように書くことができます。もちろん、非公開の場合は誰も読むことはできません。読み取り専用操作を作成するには、プライベート メンバー変数にアクセスする getColor() メソッドを定義します。
このバージョンの RGB オブジェクトは、常に有効な状態になります。
願わくば、これが OOP の性質に光を当て、考えるきっかけを与えてくれることを願っています。