Еще в ноябре 2005 года на встрече в Париже разработчики обсудили новые возможности следующей, шестой, версии PHP. Интересует ли Вас, какой будет эта версия? Примите участие в опросе, который проводится на сайте рассылки.
[опрос на английском языке: PHP 6: Are you interesting in? (PHP 6: Вы зантересованы?) - YES (ДА) - NO (НЕТ)]
PHP 5: Новые возможности.
Полиморфизм
The Pterodactyl
Copyright 2006 Pterodactyl's School
Copyright 2006 Pterodactyl's School.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
14.04.2006
История переиздания
Издание 1.00
[ Дата ]
Первоначальная версия.
Аннотация
Использование новых возможностей PHP 5 для практической реализации идей полиморфизма.
Под полиморфизмом в объектно-ориентированном программировании понимается способность объектов, принадлежащих к различным классам, отвечать специфическим для каждого класса поведением на вызов общего для всех классов метода с одним и тем же названием.
Рассмотрим, как идеи полиморфизма могут быть реализованы в рамках объектной модели PHP 5. Но прежде рассмотрим обычный стиль программирования, чтобы лучше понять преимущества полиморфизма.
<?php
class Animal {
protected $name;
function __construct($name)
{
$this->name = $name;
}
}
class Dog extends Animal {
public function burk()
{
print "$this->name: bow-wow!\n";
}
}
class Cat extends Animal {
public function mew()
{
print "$this->name: mew!\n";
}
}
?>
<?php
$animals[] = new Dog('Greta');
$animals[] = new Cat('Neko');
$animals[] = new Cat('Sindycat');
foreach ($animals as $animal) {
if ($animal instanceof Dog) {
$animal->burk();
} elseif ($animal instanceof Cat) {
$animal->meow();
} else {
print "ERROR: Invalid Object.\n";
}
}
?>
Greta: bow-wow!
Neko: mew!
Sindycat: mew!
Легко заметить, что такой подход к решению задачи не позволяет легко и удобно расширять набор поддерживаемых классов. Действительно, каждый новый класс потребует новой ветки elseif в контрольной структуре.
Такой код нельзя считать ни эффективным, ни надежным. К счастью, PHP 5 позволяет воспользоваться куда более изящным решением.
Объявим абстрактный публичный метод makeSound класса Animal и определим этот метод для каждого класса-наследника.
<?php
abstract class Animal {
protected $name;
function __construct($name)
{
$this->name = $name;
}
abstract public function makeSound();
}
class Dog extends Animal {
public function makeSound()
{
print "$this->name: bow-wow!\n";
}
}
class Cat extends Animal {
public function makeSound()
{
print "$this->name: mew!\n";
}
}
?>
Теперь контрольная структура значительно упрощается и, главное, больше не требует изменения при добавлении новых классов.
<?php
$animals[] = new Dog('Greta');
$animals[] = new Cat('Neko');
$animals[] = new Cat('Sindycat');
foreach ($animals as $animal) {
if ($animal instanceof Animal) {
$animal->makeSound();
} else {
print "ERROR: Invalid Object.\n";
}
}
?>
Greta: bow-wow!
Neko: mew!
Sindycat: mew!
Если же предполагается, что, помимо животных, могут использоваться и другие звучащие объекты (например, музыкальные инструменты), то целесообразнее воспользоваться интерфейсом.
<?php
interface SoundMaker {
public function makeSound();
}
abstract class Animal implements SoundMaker {
protected $name;
function __construct($name)
{
$this->name = $name;
}
}
abstract class Instrument implements SoundMaker {
protected $name;
function __construct($name)
{
$this->name = $name;
}
}
class Dog extends Animal {
public function makeSound()
{
print "$this->name: bow-wow!\n";
}
}
class Cat extends Animal {
public function makeSound()
{
print "$this->name: mew!\n";
}
}
class Drum extends Instrument {
public function makeSound()
{
print "$this->name: drum! drum! drum!\n";
}
}
?>
<?php
$objects[] = new Dog('Greta');
$objects[] = new Cat('Neko');
$objects[] = new Drum('Drum');
foreach ($objects as $object) {
if ($object instanceof SoundMaker) {
$object->makeSound();
} else {
print "ERROR: Invalid Object.\n";
}
}
?>