За последние 24 часа нас посетили 17839 программистов и 1612 роботов. Сейчас ищут 1358 программистов ...

Полиморфизм классов в PHP

Тема в разделе "PHP для новичков", создана пользователем Киря, 8 май 2010.

  1. Киря

    Киря Активный пользователь

    С нами с:
    20 янв 2007
    Сообщения:
    37
    Симпатии:
    0
    Адрес:
    Феодосия
    Простой пример:

    <?php
    class A {
    // Выводит, функция какого класса была вызвана
    function Test() { echo "Test from A\n"; }
    // Тестовая функция — просто переадресует на Test()
    function Call() { Test(); }
    }

    class B extends A {
    // Функция Test() для класса B
    function Test() { echo "Test from B\n"; }
    }

    $a=new A();
    $b=new B();

    $a->Call(); // выводит "Test from A"
    $b->Test(); // выводит "Test from B"
    $b->Call(); // Внимание! Выводит "Test from B"!
    ?>

    В этом примере функция Call() не передает никаких данных функциям Test(), а просто их вызывает.
    Как поступить с функцией Call(), если необходимо передать в в функции Test() разное количество переменных? Например, функции Test($x) класса А нужно передать одну переменную, а для класса В Test($x,$y) - 2 переменных.
    Надеюсь на вашу помощь.
     
  2. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    в случае, если говорим о полиморфизме, то никак. Полиморфизм подразумевает наличие методов с одинаковыми именами и сигнатурами (количиство и имена параметров должны сохраняться).

    PHP:
    1. <?php
    2. abstract class A {
    3.     private $vars;
    4.  
    5.     abstract protected function Test($vars);
    6.  
    7.     public function get()
    8.     {
    9.         $vars = array();
    10.         if (func_num_args()) {
    11.             foreach(func_get_args() as $v) {
    12.                 $vars[] = $v;
    13.             }
    14.             $return = $this->Test($vars);
    15.         } else {
    16.             $return = 'ошибка';
    17.         }
    18.         return $return;
    19.     }
    20. }
    21.  
    22. final class B extends A {
    23.  
    24.  
    25.     final protected function Test($vars)
    26.     {
    27.         return __CLASS__.':<br /><pre>'.print_r($vars,true).'</pre>';
    28.     }
    29. }
    30.  
    31. final class C extends A {
    32.  
    33.  
    34.     final protected function Test($vars)
    35.     {
    36.         return __CLASS__.':<br />'.count($vars);
    37.     }
    38.  
    39. }
    40.  
    41. $b=new B();
    42. $c=new C();
    43.  
    44. echo $b->get('1','2','3');
    45. echo '<br />';
    46. echo $c->get('1','2');          
    47. ?>
    можно вот так извернуться, по идее.

    А можно вообще не выделываться и просто переписать нужные методы при наследовании
    PHP:
    1. <?php
    2. class A {
    3.     public function Test($x) {
    4.         return 'Класс: '.__CLASS__.'<br />'.$x;
    5.     }
    6. }
    7.  
    8. final class B extends A {
    9.  
    10.  
    11.     final public function Test($x, $y)
    12.     {
    13.         $return = parent::Test($x).'<br />';
    14.         $return .= 'Класс: '.__CLASS__.'<br />'.$x.' => '.$y;
    15.         return $return;
    16.     }
    17. }
    18.  
    19.  
    20. $a=new A();
    21. $b=new B();
    22.  
    23. echo $a->Test('1');
    24. echo '<br />';
    25. echo $b->Test('1','2');
    26. ?>
     
  3. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Luge
    А во втором варианте PHP разве не ругнется, что потомок должен иметь такую же сигнатуру как и предок?
    Или весь цимис в final?
     
  4. Киря

    Киря Активный пользователь

    С нами с:
    20 янв 2007
    Сообщения:
    37
    Симпатии:
    0
    Адрес:
    Феодосия
    Luge
    Второй вариант проще и понятней. Благодарю.
    Volt(220)
    Нет, не ругается.
     
  5. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    а вот и да
    Но не ругается
     
  6. PHP:
    1. //will do the trick.
     
  7. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    5.2.10 error_reporting(-1); и error_reporting(E_ALL | E_STRICT);
     
  8.  
  9. Ах да. Забыл сказать, как это делаю я:

    PHP:
    1. <?php
    2. class A {
    3.     public function test(array $params) {
    4.  
    5.     }
    6. }
    7. class B extends A {
    8.     public function test(array $params) {
    9.     }
    10. }
    11. ?>
     
  10. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    ну и как это называется? В 5.3 поправили объектную модель и ни гу-гу в http://www.php.net/manual/en/migration53.changes.php ?

    Хотя, для абстрактных методов ошибка вылетает
     
  11. ключевое слово тут - "поправили". Т.е. знания ООП достаточно, что бы знать, что это противоречит полиморфизму в принципе, независимо от полноты реализации в интерпретаторе.