РНР 5 в подлинникеСтраница 331 из 554 |
||
|
Гпава 33. Наследование и виртуальные методы 669 \ Листинг 33.7. Файл shapes/Shape.php <?php ## Базовый класс — геометрическая фигура, class Shape { // Любая фигура имеет координаты центра, а также масштаб. // Делая координаты скрытыми членами класса, мы гарантируем, // что никто не сможет изменять их напрямую, private $х=0, $у=0, $scale=1.0; // Конструктор класса. Отображает фигуру на экране. public function _construct!) { $this->show(); } // Деструктор класса. Стирает фигуру с экрана. public function _destructO { $this->hide(); } // Переместить фигуру на ($dx, $dy) точек, public final function moveBy($dx, $dy) { // Вначале стираем фигуру с экрана. $this->hide(); // Затем изменяем координаты. $this->x- += $dx; $this->y += $dy; // Наконец, выводим фигуру на новом месте. $this->show(); > // Изменить масштаб отображения фигуры, public final function resizeBy($coef) { $this->hide(); $this->scale *= $coef; $this->show(); } // Методы возвращают координаты центра и масштаб. public final function .getCoord() { return array($this->x, $this->y); } public final function getScale() { return $this->scale; } //** //** "Защищенные" методы, доступные только для производных классов. //** Вызывать их в программе напрямую нельзя (да и не нужно). protected function hide() { die("Что здесь делать? Неизвестно!"); ) protected function show() { die ("Что здесь делать? Неизвестно!"); ) } ?> Предполагается, что для вызывающей программы фигура всегда видна на экране: в какой бы момент ни происходило обращение к методам класса, фигура нарисова- 670 Часть V. Объектно-ориентированное программирование на РНР на. В принципе, это логично: стирание изображения — это сугубо служебная операция. Представьте, как бы это выглядело, если бы в реальном мире объекты могли исчезать. То же самое — ив нашей программе: фигуры можно передвигать и масштабировать, но стирать — никогда (разве что только при уничтожении). Итак, мы установили, что такое "перемещение фигуры" с точки зрения вызывающей программы: фигура исчезает в одном месте экрана и тут же появляется уже в другом, причем можно считать, что промежуток времени между стиркой и прорисовкой — нулевой (в него не может "вклиниться" ни одна другая операция вызывающей программы). Для гарантии того, что все геометрические фигуры будут вести себя одинаково, мы объявляем публичные методы финальными (final). Таким образом, их уже нельзя будет переопределить в производных классах, а значит, фигуры не смогут "отойти от принятых канонов". Данное ограничение, конечно, является очень жестким; тем не менее в учебных целях мы пойдем на этот шаг. Виртуальные методы Давайте взглянем на листинг 33.7 (метод moveBy()) и посмотрим, как реализовано передвижение (или изменение размера), что называется, "на низком уровне". Делается это в три этапа: 1. Стираем фигуру. 2. Изменяем ее координаты или масштаб, которые хранятся в свойствах класса. 3. Рисуем фигуру уже на новых координатах. Из листинга 33.7 также видно, что при создании объекта-фигуры он тут же рисуется на экране, а при уничтожении — стирается. Это логично: уничтожение фигуры подобно аннигиляции объекта в реальном мире. Но вспомним, что при описании класса shape мы не делаем никаких предположений о типе фигуры. Как же мы можем ее в таком случае стереть с экрана, а потом — нарисовать? Вот тут в силу и вступают так называемые виртуальные методы. Виртуальным называют метод, который может переопределяться в производном классе. А в нашем случае функции show о и hide о являются виртуальными, и даже более того: в классе shape мы не знаем, как они должны быть "устроены", потому что у нас еще нет информации о типе фигуры. Таким образом, вызывать виртуальные методы Shape бессмысленно, что подчеркивается запуском встроенной функции die () В НИХ (СМ. ЛИСТИНГ 33.7). Виртуальные методы базового класса, которые бессмысленно и даже запрещено вызывать непосредственно, называют абстрактными. Вообще, "абстракция" — это такая "сущность", которая не существует сама по себе и требует дальнейшего уточнения ("реализации"). Как видите, данный термин как нельзя лучше подходит для описания "заглу-шечных" методов, а также классов, для которых не известно до конца, как они будут реализованы в будущем. ![]()
|
| |
|
В начало ←предыдущая следующая→ ... 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 ... | ||