Объекты всегда должны быть в действительном состоянии . Это означает, что объект всегда ведет себя (методы) и содержит информацию (переменные-члены), которая имеет смысл. Целью конструктора является создание объекта в допустимом состоянии.
При рассмотрении объектов-значений конструктор должен принимать минимальное количество аргументов, чтобы объект имел смысл. Например, если у вас есть объект значения RGB, имеет ли смысл в вашем приложении, если красный - это строка «обезьяна», зеленый - это 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 всегда имеет три значения, красное, синее и зеленое, и что все они являются числами от 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
Если ваш конструктор требует трех аргументов, и он выдает исключение, если все три не являются числами от 0 до 255, вы всегда будете определять переменные-члены с хорошими значениями.
Вы также должны убедиться, что красные, синие и зеленые переменные-члены являются закрытыми. Иначе любой может написать им что угодно. Конечно, если они частные, никто не может их прочитать. Чтобы создать операцию только для чтения, мы определяем метод getColor (), который обращается к закрытым переменным-членам для нас.
Эта версия объекта RGB всегда будет иметь действительное состояние.
Надеюсь, это проливает некоторый свет на природу ООП и дает вам возможность начать думать.