Пользователь
0,0
рейтинг
20 августа 2008 в 19:09

Разработка → Полиморфизм для начинающих

PHP*
Полиморфизм — одна из трех основных парадигм ООП. Если говорить кратко, полиморфизм — это способность обьекта использовать методы производного класса, который не существует на момент создания базового. Для тех, кто не особо сведущ в ООП, это, наверно, звучит сложно. Поэтому рассмотрим применение полиморфизма на примере.

Постановка задачи


Предположим, на сайте нужны три вида публикаций — новости, объявления и статьи. В чем-то они похожи — у всех них есть заголовок и текст, у новостей и объявлений есть дата. В чем-то они разные — у статей есть авторы, у новостей — источники, а у объявлений — дата, после которой оно становится не актуальным.

Самые простые варианты, которые приходят в голову — написать три отдельных класса и работать с ними. Или написать один класс, в которым будут все свойства, присущие всем трем типам публикаций, а задействоваться будут только нужные. Но ведь для разных типов аналогичные по логике методы должны работать по-разному. Делать несколько однотипных методов для разных типов (get_news, get_announcements, get_articles) — это уже совсем неграмотно. Тут нам и поможет полиморфизм.

Абстрактный класс


Грубо говоря, это класс-шаблон. Он реализует функциональность только на том уровне, на котором она известна на данный момент. Производные же классы ее дополняют. Но, пора перейти от теории к практике. Сразу оговорюсь, рассматривается примитивный пример с минимальной функциональностью. Все объяснения — в комментариях в коде.

abstract class Publication
{
    
// таблица, в которой хранятся данные по элементу
    
protected $table;
    
    
// свойства элемента нам неизвестны
    
protected $properties = array();
    
    
// конструктор
    
public function __construct($id)
    {
        
// обратите внимание, мы не знаем, из какой таблицы нам нужно получить данные
        
$result mysql_query ('SELECT * FROM `'.$this->table.'` WHERE `id`="'.$id.'" LIMIT 1');
        
// какие мы получили данные, мы тоже не знаем
        
$this->properties mysql_fetch_assoc($result);
    }
    
    
// метод, одинаковый для любого типа публикаций, возвращает значение свойства
    
public function get_property($name)
    {
        if (isset(
$this->properties[$name]))
            return 
$this->properties[$name];
            
        return 
false;
    }
    
    
// метод, одинаковый для любого типа публикаций, устанавливает значение свойства
    
public function set_property($name$value)
    {
        if (!isset(
$this->properties[$name]))
            return 
false;
            
        
$this->properties[$name] = $value;
        
        return 
$value;
    }
    
    
// а этот метод должен напечатать публикацию, но мы не знаем, как именно это сделать, и потому объявляем его абстрактным
    
abstract public function do_print();
}


Производные классы


Теперь можно перейти к созданию производных классов, которые и реализуют недостающую функциональность.

class News extends Publication
{
    
// конструктор класса новостей, производного от класса публикаций
    
public function __construct($id)
    {
        
// устанавливаем значение таблицы, в которой хранятся данные по новостям
        
$this->table 'news_table';
        
// вызываем конструктор родительского класса
        
parent::__construct($id);
    }
    
    
// переопределяем абстрактный метод печати
    
public function do_print()
    {
        echo 
$this->properties['title'];
        echo 
'<br /><br />';
        echo 
$this->properties['text'];
        echo 
'<br />Источник: '.$this->properties['source'];
    }
}

class 
Announcement extends Publication
{
    
// конструктор класса объявлений, производного от класса публикаций
    
public function __construct($id)
    {
        
// устанавливаем значение таблицы, в которой хранятся данные по объявлениям
        
$this->table 'announcements_table';
        
// вызываем конструктор родительского класса
        
parent::__construct($id);
    }
    
    
// переопределяем абстрактный метод печати
    
public function do_print()
    {
        echo 
$this->properties['title'];
        echo 
'<br />Внимание! Объявление действительно до '.$this->properties['end_date'];
        echo 
'<br /><br />'.$this->properties['text'];
    }
}

class 
Article extends Publication
{
    
// конструктор класса статей, производного от класса публикаций
    
public function __construct($id)
    {
        
// устанавливаем значение таблицы, в которой хранятся данные по статьям
        
$this->table 'articles_table';
        
// вызываем конструктор родительского класса
        
parent::__construct($id);
    }
    
    
// переопределяем абстрактный метод печати
    
public function do_print()
    {
        echo 
$this->properties['title'];
        echo 
'<br /><br />';
        echo 
$this->properties['text'];
        echo 
'<br />&copy; '.$this->properties['author'];
    }
}


Теперь об использовании


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

// наполняем массив публикаций объектами, производными от Publication
$publications[] = new News($news_id);
$publications[] = new Announcement($announcement_id);
$publications[] = new Article($article_id);

foreach (
$publications as $publication) {
    
// если мы работаем с наследниками Publication
    
if ($publication instanceof Publication) {
        
// то печатаем данные
        
$publication->do_print(); 
    } else {
        
// исключение или обработка ошибки
    
}
}


Вот и все. Легким движением руки брюки превращаются в элегантные шорты :-).

Основная выгода полиморфизма — легкость, с которой можно создавать новые классы, «ведущие себя» аналогично родственным, что, в свою очередь, позволяет достигнуть расширяемости и модифицируемости. В статье показан всего лишь примитивный пример, но даже в нем видно, насколько использование абстракций может облегчить разработку. Мы можем работать с новостями точно так, как с объявлениями или статьями, при этом нам даже не обязательно знать, с чем именно мы работаем! В реальных, намного более сложных приложениях, эта выгода еще ощутимей.

Немного теории

  • Методы, которые требуют переопределения, называются абстрактными. Логично, что если класс содержит хотя бы один абстрактный метод, то он тоже является абстрактным.
  • Очевидно, что обьект абстрактного класса невозможно создать, иначе он не был бы абстрактным.
  • Производный класс имеет свойства и методы, принадлежащие базовому классу, и, кроме того, может иметь собственные методы и свойства.
  • Метод, переопределяемый в производном классе, называется виртуальным. В базовом абстрактном классе об этом методе нет никакой информации.
  • Суть абстрагирования в том, чтобы определять метод в том месте, где есть наиболее полная информация о том, как он должен работать.

UPD: по поводу sql-inj и нарушения MVC — господа, это просто пример, причем пример по полиморфизму, в котором я не считаю нужным уделять значения этим вещам. Это тема для совсем других статей.

Оригинал у меня на сайте
Андрей Сабинин @s_a_p
карма
48,6
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (130)

  • –1
    А тут нет блога «Для начинающих»?

    А то статейка то хорошая, некоторым полезная…

    Но ведь шапками то закидают, на тему что всем это и так известно и что РНР тут совсем краешком…
    • 0
      Такого блога не нашел. Если есть, подскажите, я перенесу.

      Обычно полиморфизм рассматривают на примере геометрических фигур. Я специально подобрал пример, хоть как-то совместимый с web и php в частности.
      • +1
        habrahabr.ru/blogs/la_france/, я думаю вот сюда надо перенести
      • –14
        s_a_p, пожалуйста, срочно примите меры — представленный код не выдерживает почти никакой критики.

        > echo '

        '
        это плохая практика! есть шаблоны и MVC

        > $result = mysql_query ('SELECT * FROM `'.$this->table.'` WHERE `id`=«'.$id.'» LIMIT 1');
        одна строчка содержит сразу четыре ошибки: это не result это query, две уязвимости по sql injection и синтаксическую ошибку SQL в виде русских кавычек

        > properties
        использование массива для представления свойсв объекта в динамическом языке — крайне спорная идея.

        Пожалуйста, уберите статю, пока ещё сотня людей не прочитала это со словами «Хорошая статья!»

        Проявите ответственность перед хабраобществом!!! Вам же стыдно потом будет.

        «Папа (дедушка?), а почему ты в 2008 году не позаботился о проверке введённых get-параметров? Ты разве не знал?»
        • +5
          Вы понимаете, статья совсем не про MVC и совсем не про SQL-запросы и совсем не про проверку поступающих данных.
          Она про полиморфизм. А этот код приведен просто для большей наглядности.
        • –3
          Ну что вы придираетесь, это же урок по полиморфизму, а не по защите от XSS и прочим правильностям. Если все указанное учитывать то никто урок по полиморфизму не усвоит.
        • –3
          Не забывайте что статья расчитана не на «Вас», а для новичков. Трудно очень подобрать пример, где не будет MVC, SQL-ijection и прочего. Как вы представляете должна выглядит статья?
          • 0
            Как вы представляете должна выглядит статья?

            статья должна соответствовать названию, то есть быть про полиморфизм
          • +2
            >Не забывайте что статья расчитана не на «Вас», а для новичков.
            Как поступают новички с такими вещами?? правильно ctr+c ctr+v=> sql injection, смотрим чем забиты багтреки на том же секлабе. :(

            Намного более удачные примеры на
            www.php.net/manual/ru/language.oop5.abstract.php в коментариях.

            P.S. Нет примеров вызова класса, из-за чего статья теряет смысл на 90%, т.к. не видно выгоды в использовании, что мешао автору сделать вызов хотя бы условным оператором, не говоря уже о паттернах?

            • 0
              Для тех кто до сих пор учится с помощью ctr+c ctr+v вообще бесполезна, основная задача объяснить что это такое, и как реализуется.

              А тем кому действительно интересно они уже и найдут как дальше использовать эту информацию…
            • НЛО прилетело и опубликовало эту надпись здесь
          • –4
            с одной стороны вы правы, с другой, те же начинающие, прочитавшие вашу статью, могут подумать, что в ней все изначально верно и корректно («это же статья от гуру и он учит нас, значит там не может быть ошибок») и в итоге будут сами программировать с ошибками, только потому, что возьмут ваши примеры, приведенные в статье за истину.

            Вывод: конечно нужно подбирать примеры простые для понимания, но не стоит заключать в примеры заранее известные уязвимости. иначе не ясно — во благо ли ваша статья.
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            >ведь всеравно буду скрипты ваять ;-)
            Отлично сказанная фраза)) Поддерживаю, так как такой-же, как и вы, начинающий (ведь вы — такой?) в ООП.
      • +1
        Обучая или собеседуя кого-нибудь, люблю задавать вопрос из книжки Боба Мартина: что от чего следует наследовать квадрат от прямоугольника или наоборот.
        Правильно ответил только один человек, который читал Боба Мартина.
        • 0
          Я Боба Мартина не читал, но мне кажется, что их обоих следует наследовать от класса многоугольник? :)
          • 0
            бинго!
            • 0
              Наследовать нада от класа «фигура» и там уже переопределять методы и добавлять углы, вес и всё что хотите.
            • 0
              Тупой ответ. В вопросе — два параметра. А придумывать третий — не сказано в условии. Вам дали 2 спички — работайте с ними, а не тащите свой коробок куда не нужно.

              « — Что вы будете — вино или водку?
              — И пиво тоже!»
              Глупости.
        • 0
          При первом приближении кажется что квадрат нужно наследовать от прямоугольника, т.к. квадрат является частным случаем прямоугольника, но т.к. квадрат является также частным ромба, то правильней обоих наследовать от класса 'четырехугольник'.
          • 0
            Я делаю допуск, что других разновидностей многоугольников нет.
            Только квадрат и прямоугольник
            • 0
              Если кроме квадрата и прямоугольника в системе нет других многоугольников и никогда точно не будет, есть смысл сделать так, как кажется при первом приближении.
              • +1
                Наследовать квадрат и прямоугольник один от другого (неважно в какой иерархии) — то же самое, что наследовать круг одного радиуса от круга другого радиуса.
            • 0
              Квадрат должен имплементить интерфейсы ромба и прямоугольника, которые, в свою очередь происходят из многоугольников )

              Как-то так )
              • –5
                Прошу господ меня извинить: напился, фигню-с сморозил-с )
          • 0
            пока писал, уже успели дать правильный ответ. =)
        • НЛО прилетело и опубликовало эту надпись здесь
        • +1
          наследовать надо от того, от чего будет эффективней в рамках поставленной задачи. в таком виде, как у вас, вопрос не имеет смысла.
  • 0
    Хорошая статья!
    Автор не хочет написать в таком же стиле например о наследовании?
    • –1
      Спасибо, попробую :)
      • 0
        Мы будем очень рады увидеть такую статью!

        Только пожалуйста, подойдите к вопросу отвественно и не допускайте столь грубых ошибок!

        Абстрактные понятия объектно-ориентированного программирования вообще лучше описывать в «псведокоде», но не как не на PHP
    • +3
      Собственно говоря в статье и можно наблюдать пример наследования. От абстрактного класса. Сути же полиморфизма вообще не продемонстрировано (т.е. где и как использовать этих наследников).
    • 0
      А по-моему, статья и есть о наследовании, просто с использованием асбтракного класса.
      А полиморфизм как таковой тут не затрагивается.
  • +5
    Вобщем, описывать полиморфизм на основе ПХП — спорное занятие. Основной метод полиморфизма — интерфейсы, а не наследование. В пхп интерфейсы «какбэ есть», но их ценность под большим вопросом.
    • 0
      Насчёт основного метода можно спорить, но есть «народные приметы». Интерфейсы+полиморфизм — к более читабельному коду, абстрактные классы+полиморфизм — к долгим часам отладки. Для этого есть фундаментальные причины.
  • +5
    Имхо термин «полиморфизм» более к месту в языках со строгой типизацией, где за ним стоит термин «приведение типов». Хотя и придумать более подходящие название не получается :/
  • 0
    Хорошая статья, спасибо. Если кому-то нужен пример «сложного приложения» с использованием полиморфизма — можно покопать код Zend Framework. Код понятный и хорошо документирован.
  • +14
    > полиморфизм — это способность обьекта использовать методы производного класса, который не существует на момент создания базового

    М-да… Хоть бы сами выяснили что это такое, прежде чем постить. Хотя бы здесь: ru.wikipedia.org/wiki/Полиморфизм_в_языках_программирования

    >> Полиморфизм — взаимозаменяемость объектов с одинаковым интерфейсом.

    Или, говоря более простым языком (и в контексте языков с «традиционным» ООП), полиморфизм — это возможность использования экземпляра класса-наследника там, где требуется экземпляр базового класса. (Это определение можно легко расширить и на интерфейсы, если учесть, что интерфейс — это чисто абстрактный класс.)

    Но существуют «немного другие» модели ООП, где наследования нет и поэтому определение из Википедии более корректно, так как оно верно для обоих случаев.

    То, что вы назвали полиморфизмом, на самом деле — принцип работы виртуальных функций.

    > Метод, переопределяемый в производном классе, называется виртуальным.

    Может в PHP оно и так, но вообще — нет.

    • +3
      да так и есть, стандартная задачка на полиморфиз — теплица))

      а конкретнее датчики теплицы: все они есть наследниками абстрактного класса, и дальше они имеют один интерфейс
      • +5
        Чувствуется Гради Буч. ;-)
    • 0
      >> Метод, переопределяемый в производном классе, называется виртуальным.

      >Может в PHP оно и так, но вообще — нет.

      И в PHP не так.
    • +2
      УРА! наконец-то написали что такое полиморфизм. вся ветка темы ПОЛИМОРФИЗМ рассуждает с видом знатоков о наследовании, о том для новичков ли эта статья, но почти никто не сказал по делу.
      почти никто из комментивших не понимает что такое полиморфизм ((
  • +1
    Пример действительно для новичков.
    Есть значительно более продуманные вещи, например, GenericObject, который позволяет работать с любыми сущностями. Осуществлять в них в том числе и редактирование и удаление.

    И как вы предполагаете работу со списками, например, статей. Или для этого вы создадите класс, который никак не будет связан с существующими?
    • +1
      «Пример действительно для новичков» ещё и от новичка, видимо.
      предупреждать надо!

      а ещё лучше — посоветоваться с опытными людьми перед публикацией

      где ответственность перед хабраобществом??
  • +3
    Всё не так. Начиная с того, что классы поименованы во множественном числе.
    • –2
      Вообще всё не так.
      • –3
        напишите так, пожалуйста…
        напишите…
        хотя бы переписать этот пример ТАК
        или на другом примере объясните
        • +2
          Для того, чтобы статья стала статьей о полиморфизме, нужно добавить:
          function pub_factory($type) {...}
          pub_factory(«news»)->do_print();
          Ну или еще как либо обозначить полиморфное использование этих классов.
  • 0
    Производный класс имеет свойства и методы, принадлежащие базовому классу, и, кроме того, может иметь собственные методы и классы.

    Наверное, имелось ввиду методы и свойства
  • +7
    УБЕРИТЕ ЭТО НЕМЕДЛЕННО

    Уважаемый автор, я безусловно ценю вашу попытку помочь начинающим программистам, но Вы, похоже, и сам — начинающий?

    ('SELECT * FROM `'.$this->table.'` WHERE `id`=«'.$id.'» LIMIT 1')

    так делать нельзя.
    Есть такая штука, как prepared statement и sql-injection.

    ПРОШУ ВАС, перепишите это или уберите.
    Нельзя новичков приучать писать априори небезопасный код.

    И вовсе это не «result».

    Предлагаю всю работу с БД заменить комментарием: «в этом медоде мы достаём из таблицы $t одну запись по идентификатору $id».

    • 0
      гы. :) я даже не вчитывался в запрос. просто пропустил его как коментарии вида «// конструктор» )))))
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        простите, мудофил это кто?

        aivee, а у Вас есть что сказать от своего имени, без «©»?
        • НЛО прилетело и опубликовало эту надпись здесь
      • –5
        Первый раз вижу такую неадекватную реакцию на упоминание об sql-injection…
    • –3
      Забавно, «Профессиональный программист Андрей Сабинин» (http://s-a-p.in/)

      Имеет весьма визуально приятную страничку с неплохим текстом.

      «Заказывая у меня сайт, вы гарантированно получите качественно выполненную работу. У вас не будет головной боли о бесперебойности работы вашего сайта и его защищенности — он будет в работе 24 часа в сутки 7 дней в неделю и будет эффективно выполнять свои цели»

      порадовало =)
      • 0
        Плохое настроение?
  • –1
    Статья гуд.
    Блог для начинающий программеров — нужно бы создать. (не просто «для начинающих»)
    в таком духе изложения не против почитать даже основы php, которые знаю :)
  • +1
    Несмотря на обилие недовольных (к коим я абсолютно и полностью присоединяюсь) — статья попала на главную… На хабре действительно так много людей, которым кажется, что статья хороша?..
    • +2
      да, к сожалению.

      наша задача (в качестве более опытных участников) — убрать статью с главной страницы!

      при этом, карму автору убирать не надо. человек старался всё-таки =)
      • НЛО прилетело и опубликовало эту надпись здесь
        • +2
          Я, конечно, извиняюсь, но чему вас научил автор статьи? Своим собственным «принципам ООП»? Я не буду вдаваться в подробности относительно кода (хотя он мне тоже не нравиться, но бывает и хуже), я лишь скажу, что если вы будете учить теорию по подобным статьям, то в конечном счете об ООП вы будете знать довольно мало.
          • НЛО прилетело и опубликовало эту надпись здесь
            • +1
              Всё уже давно написано. Почитай Гради Буча «Объектно-ориентированный анализ и проектирование».
              • НЛО прилетело и опубликовало эту надпись здесь
        • 0
          хуиту гоните.
          почитайте книжки, и у вас отпадет желание вникать в статьи такого рода.
          благодаря таким как вы интернет становится помойкой, где любое говно будет востребованным, только бы офисный планктон и школиё могли бы убить свое время.
          • НЛО прилетело и опубликовало эту надпись здесь
  • +1
    Только мне показалось, что тут рассматривается совсем не там парадигма?
    • 0
      *не та
    • –2
      тут вообще всё спорно =)
  • НЛО прилетело и опубликовало эту надпись здесь
    • –3
      Как минимум 3 преимущества:

      1. они быстрее
      2. они могут быть документированы
      3. имеют поддержку в IDE

      Первое непринципиально лично для меня, вторые два — вполне себе преимущества.
      • НЛО прилетело и опубликовало эту надпись здесь
        • 0
          1. Я же примерно то же и написал.
          2. Нет, попробуйте в __get сделать документацию для десятка разных переменных, которые он может вернуть.
          3. Следует из второго — в доках можно юзать phpdoc, тем самым заставляя нормальные IDE делать вам всевозможные подсказки.
          • НЛО прилетело и опубликовало эту надпись здесь
  • +2
    обычное наследование, обычное переопределение, а где полиморфизм?

    p.s. создавать в классах-наследниках конструктор совсем было необязательно, можно было просто инициализировать переменную как свойство класса
  • –4
    Поразила фраза «для тех, кто не особо сведущ в ООП» =)

    Не, а что правда можно программировать и не знать об этом?
    • 0
      Можно и еще как. Очень многие подобными ужасами занимаются, потом приходишь, смотришь на кучу файлов в куче директорий и плохо становится. Не в обиду сказано тем, кто не приверженец ООП.
      Просто к хорошему быстро привыкаешь :)
    • +1
      Есть не только ООП языки программирования
      • 0
        я в курсе, но кроме того, что мы изучаем язык программирования, мы обычно изучаем некоторые концепты в этой области. Концепт ООП — довольно значимая часть теории языков, разве не?
        • +2
          У меня есть друг, он отлично программирует на ассемблере и на C микроконтроллеры, можно сказать гуру в этом. Он понятия не имеет что такое полиморфизм, про ООП что-то слышал, но не использовал, ему просто не нужно.

          Так что не все программисты одинаково полезны.
    • +1
      Не знать про ООП? Да как нефик делать. Например в JS классический ООП нафик не нужно знать — там все делается прототипы, замыкания и функторы. Lisp / Scheme — вообще ту применить любую парадигму, какая душе угодна.

      А вообще, открою вам страшную тайну. Только цсс, ни-ко-му! [шепотом]: объектов не существует!

      • –3
        вы смешной :)

        меня поразил не тот факт, что есть ещё функциональная прадигма и там, алгоритмическая, а именно факт незнания технологии ООП. Наверно, я зажралась и считаю это элементарным минимумом
        • 0
          Ну… до ООП надо еще дойти. Желательно самому. Ибо когда у человека есть на практике проблема а-ля [«это выглядит слишком громоздко», «слишком много повторений», «мне надоело тягать этот указатель из функции в функцию», «половина функций для работы с моими структурами являются клонами»], то эффект от осознания парадигмы ООП можно сопоставить… ну… э… как если бы вас шарахнуло молнией — помню по себе, когда в 1991 году я прикупил мааленькую брошурку за авторством Славы Чипа (вероятно, псевдоним), популярным языком объяснявшую суть ООП с примерами на BP — не передать словами, какие мысли вертелись в моей голове тогда ;-)
    • 0
      многие не знают не только об объектно ориентированном программировании, но даже об бъектно ориентированном проекутировании. и получается недокод код, но иногда он работает :(
      • 0
        И бывает даже такое, что люди считают объектно ориентированным программированием оборачивание функций в классы и вызов этих функций как статических методов классов.

        Заблуждение возникает от нежлания разобраться в предмете.
  • +8
    Полное непонимание автором предмета. Жаль молодежь съест, долго переучиваться от таких статей. И даж не в инжекшене дело, это еще мелочи по сравнению с таким полиморфизмом. Бред.
    • 0
      Прошу прощения, не все так плохо. Повторюсь:
      Для того, чтобы статья стала статьей о полиморфизме, нужно добавить:
      function pub_factory($type) {...}
      pub_factory(«news»)->do_print();
      Ну или еще как либо обозначить полиморфное использование этих классов.
      • 0
        не совсем так. должна быть функция а-ля

        function foo(publications $p) { $p->do_print(); }

        вот тогда это будет статья про полиморфизм. ;-)
        • 0
          Поверьте, это одно и то же. Более того, мой пример именно из жизни этой статьи, плюс показывает, что такое фабрика ;).
          В моем случае страница будет выведена как-то так:
          pub_factory($_GET['page'])->do_print(); // Тут, для пристающих к мелочам, должен быть еще один отнаследованный класс обрабатывающий неизвестные страницы (сообщение об ошибке или редирект)
          В вашем же случае это все делается явно, тогда вообще не понятно для чего foo():
          switch ($_GET['page'])
          {
          case 'news': $pub = new news();

          }
          foo($pub);
          Если же вы увидели разницу между передачей в функцию полиморфного объекта как аргумента и его возвратом из функции, плохо:(.
          Смотрю на комменты, в основном безнадега(((.
          • 0
            Гм-гм… То есть, Вы утверждаете, что:

            function factory($class) {
            return new $class();
            }
            factory(«news»)->do_print();

            отражает суть полиморфизма? :))
            • 0
              Конечно ;). Единственное для полной ясности нужно добавить:
              function factory($class) {
              if (...) return new $class();
              else return new $class();
              }
              factory(«news»)->do_print();
              По факту он самый и есть ;)
              • 0
                И в какой строчке у Вас, простите, полиморфизм? :)
                • 0
                  factory(«news»)->do_print(); тута ;) вот как раз у стрелочки ;)
                  по факту (понятно с учетом того, что передаем мы не константу «news», а заранее неизвестное значение, а то нечестно получается;) мы не знаем динамический тип возвращаемого фабрикой объекта. только статический, в интерфейсе которого есть do_print (я тут рассуждаю со скидками касательно очень не строгой типизации в PHP). так вот вызывая у переопределенный метод do_print в иерархии publications мы получаем полиморфное поведение возвращаемого объекта, т.е. разное поведение в зависимости от динамического типа. Опять же, нет никакой разницы между вашим примером и моим, какая разница возвращать или передавать как аргумент в функцию объект? Может я не совсем понимаю в чем именно вы не согласны? А то обсуждение затянулось?;)
                  • 0
                    О-хо-хо, теперь я понял вашу мысль. Только, имхо, объяснить ньюбу разницу между

                    factory(«news»)->do_print();

                    и

                    $news = new news();
                    $news->do_print();

                    будет очень непросто. Хотя бы потому, что в PHP не декларируется тип возвращаемого значения функции.
                    • 0
                      Согласен, новичку пожалуй тяжелее понять.
    • +1
      > Жаль молодежь съест
      уже
  • 0
    Название класса с маленькой буквы смотрится как-то… ну, скажем, неэстетично.
    • НЛО прилетело и опубликовало эту надпись здесь
  • +4
    Я бы на месте автора учел все замечания и выложил обновленный код дабы реабилитироваться. Ну, конечно, если автор не новичок, как здесь предполагалось, и способен исправить все недоработки. По-моему, это было бы достойно. Критиковать и ошибаться мы все умеем, а вот несмотря на критику, взять и довести дело до ума — это уже совсем другое.
    • 0
      Поддерживаю, хоть и нет патронов.
      • –4
        Да, я неудачник, закончились: D
    • 0
      умение с легкостью принимать критику — первый признак профессионализма.
  • –7
    статья вообщем немного полезна, но как было написано выше в комментах к статье — о безопасности нужно думать тож:)(про определение полиморфизма повторяться не буду )
    Но всё равно спасиб, щас как раз изучаю фраемворк — вы как раз во время написали...)
  • +1
    Не учите детей плохому! Лучше дайте им почитать Страуструпа!

    Это моё imho, что лучше учится ООП на языках со статической типизацией.
    • –3
      Помоему, Страструпа, насколько бы он не был хорош, читать без хорошего знания С++ нестоит. После этого может долго мучить ощущение что плюсы это что то монструозное очень сложное, и что это вообще невозможно выучить.
      • +1
        Его нужно читать, чтобы эти знания появились;)
        • –6
          Учить С++ по Страуструпу в наше время это безумие, я не говорю что его не нужно прочитать, но начинать учить язык с него совершенно не стоит. Его все-таки очень сложно читать, я думаю с этим не поспоришь. Поэтому советовать его людям только начинающим писать на пхп это, как советовать автослесарю учебник по квантовой физике, для внутреннего развития конечено полезно, но для дела нафиг не нужно.
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Грубо, конечно, но верно.
      • 0
        >Если говорить кратко, полиморфизм — это способность обьекта использовать методы производного класса, который не существует на момент создания базового.

        Всё ещё эта объява висит, несмотря на предупреждение. В том же C# существует полиморфизм с помощью классов и полиморфизм с помощью интерфейсов. То что написано в приведённом определении нелогично по своей сути, а упоминание базового и производного класса говорит больше о наследовании, а не полиморфизме.

        Лучше взять определение из вики:
        Полиморфи́зм (в языках программирования) — взаимозаменяемость объектов с одинаковым интерфейсом.
  • 0
    Не плохо бы было еще об интерфейсах упомянуть :)
  • +3
    Тема полиморфизма не раскрыта. Его тут просто нет. Наследование есть. Полиморфизм отсутствует. Можно было бы, конечно, добавить хотя бы какую-то функцию, в которую бы передавались объекты всех этих классов, а в ней дергался унаследованный метод do_print. Причем функция эта должна была обязательно принимать только объекты типа publications. Тогда бы это раскрывало, зачем тут понадобился полиморфизм. Но все равно не то. Очень многое ускользает.
    И вообще, не уверен, что полиморфизм следовало бы пытаться показать на примере PHP. Лучше всего, мне кажется, подошел бы все-таки язык со статической типизацией. Например, си++. Там бы можно было узнать точно, что такое виртуальные функции (что они вовсе не те, которые объявлены и определены в каком-то производном классе, а виртуальными они становятся еще в базовом), и что если они не виртуальные в базовом классе, то хрена лысого, при полиморфном использовании объекта, вызовется функция реально использующегося объекта, но лишь базового… зачем нужен виртуальный деструктор, и что такое срезки, и какие подлянки это все готовит… что такое чисто виртуальные функции и как их наличие делает класс абстрактным… что вообще такое позднее динамическое связывание и таблица виртуальных функций…
    нет, действительно, при попытке рассказать про полиморфизм на примере PHP очень многое, мне кажется, оказывается «за кадром», и людям, которые только знакомятся с программированием, или используют только PHP, может стать непонятным, а зачем это все нужно — какой-то полиморфизм.
    Я бы с удовольствием привел пример на СИ++, но на это потребуется отдельный топик. Комментарий для этого слишком мал и неудобен. (Пример я начал писать, но стер). Хотя тем, кто изучает программирование в универсетете, это и так расскажут и покажут, а тем у кого хобби — программирование на PHP, тем и подавно не сдался пример на си++…
    • +1
      согласен с вами.
      те кто пишет: «хорошая статья» — просто малолетнее школиё.
      про полиморфизм и прочее объясняется в любой хорошей книжке по программированию. особенно по с++.
      если человек учится по таким статьям, значит он или ленивый и ограниченный, или еще «школьник» не знающий про книжки, которые очень часто упоминаются.
  • +2
    Полиморфизм с примерами на ПэХэПэ… дожили. Я даже читать не стал ибо этот язык не может раскрыть в полной мере, что такое полиморфизм.
    • 0
      Согласен, с тем, что в PHP он далеко не полон, но если кто-то (не я) юзает только PHP? К тому же вполне полезно знать, что из полиморфизма работает именно в PHP, а главное как. Я попробовал развернуть тему немного поглубже.
  • 0
    Язык PHP, на мой взгляд, является убогим, непродуманным, в нём не место стройным концепциям ООП, которые приделаны к нему сбоку. Объектно-ориентированная идеология таких классических языков как C++ и Java воплощена в нём не полностью, а по частям, добавляемым с выходом новых версий. Например, в PHP есть указания типов объектов в списке аргументов функций (чтобы усилить модель ООП), но так как вообще в языке этого не требуется (типизация-то не статическая), такая возможность смотрится корявым костылём. Сила полиморфизма во многом именно в статической типизации, объектных ссылках определённых типов (ещё в перегруженных методах и т.д.). PHP изначально создавался как средство для написания простеньких скриптиков генерации веб-страниц, и то, что авторы пытаются добавить в него «объектно-ориентированную мощь» (опять же — in my opinion) — просто глупо.
    • 0
      P.S. следите за кармой :)
    • 0
      Вопрос как использовать. Согласен, что учиться стройным концепциям ООП на примерах PHP, это научиться не стройным, не концепциям, недоООП))). А вот если начать с языка не столь динамичного, то можно очень удачно воплощать все и в PHP. Более того, конкретно по вебу, на плюсах гораздо сложнее реализации выходят, нет там многого, что очень облегчает жизнь).
  • НЛО прилетело и опубликовало эту надпись здесь
  • 0
  • –1
    Мне понравилась статья, спасибо)
  • –4
    Ну то что автор не знает что такое полиморфизм повторяться не буду.
    Ну то что автор не использует магические __set & __get а вместо них Set_Property & Get_Property повторяться не буду.
    Ну то что у автора в статье в переменной $result образовываеться не результат а mysql_object повторяться не буду.
    Ну то что у автора вообще впринцыпе уязвимый код SQL_Inj повторяться не буду.

    И смысл такой статьи для новичков если он написан новичком. Да безусловно «срать в карму» автору не стоит он старался всёже обращаюсь к автору: Принялись что либо писать пишите сразу нормально. =(
  • +1
    > Очевидно, что обьект абстрактного класса невозможно создать, иначе он не был бы абстрактным.

    public function __construct($id){ throw new Exception( 'это абстрактный класс, итить-колотить!' ) }
  • 0
    Очень улыбнуло что в конструкторе PHP класса, не обязательно вызывать конструктор парента в первом стейтменте =))) Вам не кажется что это ОЧЕНЬ НЕ правильно? =)) Это я к тому говорю, что protected $table
    ДОЛЖЕН (MUST) быть не полем, а параметром конструктора абстрактного класса. Ну правда. А вдруг кто-то забудет инициализировать $table в потомке? Эээх…

    Не сочтите меня за сноба. но соглашусь с предыдущими ораторами. ООП нужно сначала изучить на ОО языках типа Java или C# и потом эти знания переносить на такие языки как PHP. Я совсем не против PHP — он хорош в своей области, но понимать ООП на примере PHP, это все равно что готовиться к формуле1 на КАМАЗе =)

    Anyway, спасибо автору за статью. Она заставит кодеров еще раз задуматься о спорности процедурного подхода
    • 0
      угу, главное потом не садиться писать на языках с другим ооп ( как в яваскрипте, например ), а то такие ужосы получаются… ;-)
      • 0
        Ну яваскрипт в этом плане исключение, цитата из вики:
        Прототипное программированиеПримерами языков программирования, где используется прототипное программирование, являются Self и JavaScript.
        • Создание новых объектов через клонирование прототипов.
          Повторное использование кода достигается не через наследование, а с помощью делегирования.

  • 0
    Автору спасибо за статью. Хотья уже вроде как и не начинающий, прочитал не без интереса и удовольствия.Прикольно когда «сложные» вещи объяснены «просто».
    Хех вспоминаю 1-й курс институа у нас препод по СИ был так он даже «простые» вещи объяснял «сложно».Мде а ведь это только отталкивает и отбивает охоту.
    Всё достаточно просто и доступно объяснено.Думаю эта статья должна помочь тем, кто пока плавает в ООП.
  • +1
    Вот, впервые за последнее время узнаю Хабр, хотелось бы чаще видеть здесь такие посты :(
  • 0
    Новый хабр конечно очень хорошо, но лично мне надоело уже видеть полуобрезаные строки, конец которых загораживают боковые блоки справа

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.