Отправляет email-рассылки с помощью сервиса Sendsay

PHP 5: Новые возможности.

  Все выпуски  

Полиморфизм


Вниманию читателей!

Отдельные выпуски рассылки в той или иной мере взаимосвязаны; особенно, это относится к материалам практических занятий.

С предыдущими выпусками Вы можете ознакомиться:

  1. в архиве рассылки (оригиналы выпусков);
  2. на сайте рассылки (исправленные и дополненные версии).

# # #

Вы также можете подписаться на рассылку "PHP 5 для начинающих".

PHP 6 уже в разработке!

Еще в ноябре 2005 года на встрече в Париже разработчики обсудили новые возможности следующей, шестой, версии PHP. Интересует ли Вас, какой будет эта версия? Примите участие в опросе, который проводится на сайте рассылки.

http://pterodactyl.l2p.net/e107/

[опрос на английском языке: PHP 6: Are you interesting in? (PHP 6: Вы зантересованы?) - YES (ДА) - NO (НЕТ)]

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 в контрольной структуре.

    } elseif ($animal instanceof Pig) {
        $animal->grunt();
    }
        

Такой код нельзя считать ни эффективным, ни надежным. К счастью, 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";
    }
}

?>
        
Greta: bow-wow!
Neko: mew!
Drum: drum! drum! drum!
        

Created with DocBook Created with Libxslt


В избранное