Попытка выяснить, поддерживает ли PHP такие функции, как перегрузка, наследование и полиморфизм методов, я узнал:
но я не уверен в полиморфизме. Я нашел это Google в Интернете:
Я должен отметить, что в PHP полиморфизм не совсем такой, каким он должен быть. Я имею в виду, что он действительно работает, но поскольку у нас слабый тип данных, это неверно.
Так это действительно полиморфизм?
Редактировать Просто не удается разместить определенное ДА или НЕТ рядом с PHP supports polymorphism
. Я бы не хотел утверждать: «PHP не поддерживает полиморфизм», когда на самом деле это происходит. Или наоборот.
class Animal { var $name; function __construct($name) { $this->name = $name; } } class Dog extends Animal { function speak() { return "Woof, woof!"; } } class Cat extends Animal { function speak() { return "Meow..."; } } $animals = array(new Dog('Skip'), new Cat('Snowball')); foreach($animals as $animal) { print $animal->name . " says: " . $animal->speak() . '<br>'; }
Вы можете пометить все, что хотите, но для меня это похоже на полиморфизм.
хотя PHP не поддерживает перегрузку метода, как вы это переживали на других языках, например Java. но вы можете перегружать метод в PHP, но метод определения отличается. если вы хотите иметь разную функциональность для данного метода, с различным набором параметров в PHP, вы можете сделать что-то вроде этого:
class myClass { public function overloadedMethod() { // func_num_args() is a build-in function that returns an Integer. // the number of parameters passed to the method. if ( func_num_args() > 1 ) { $param1 = func_get_arg(0); $param2 = func_get_arg(1); $this->_overloadedMethodImplementation2($param1,$param2) } else { $param1 = func_get_arg(0); $this->_overloadedMethodImplementation1($param1) } } protected function _overloadedMethodImplementation1($param1) { // code 1 } protected function _overloadedMethodImplementation2($param1,$param2) { // code 2 } }
может быть более чистая реализация, но это всего лишь образец.
PHP поддерживает наследование и интерфейсы. поэтому вы можете использовать полиморфизм. вы можете иметь такой интерфейс:
// file: MyBackupInterface.php interface MyBackupInterface { // saves the data on a reliable storage public function saveData(); public function setData(); } // file: myBackupAbstract.php require_once 'MyBackupInterface.php'; class MyBackupAbstract implements MyBackupInterface { protected $_data; public function setData($data) { $this->_data= $data; } // there is no abstract modifier in PHP. so le'ts avoid this class to be used in other ways public function __construct() { throw new Exception('this class is abstract. you can not instantiate it'); } } // file: BackupToDisk.php require_once 'MyBackupAbstract.php'; class BackupToDisk extends MyBackupAbstract { protected $_savePath; // implement other methods ... public function saveData() { // file_put_contents() is a built-in function to save a string into a file. file_put_contents($this->_savePath, $this->_data); } } // file: BackupToWebService.php require_once 'MyBackupAbstract.php'; class BackupToWebService extends MyBackupAbstract { protected $_webService; // implement other methods ... public function saveData() { // suppose sendData() is implemented in the class $this->sendData($this->_data); } }
теперь в вашем приложении вы можете использовать его следующим образом:
// file: saveMyData.php // some code to populate $myData $backupSolutions = array( new BackupToDisk('/tmp/backup') , new BackupToWebService('webserviceURL') ); foreach ( $backupSolutions as $bs ) { $bs->setData($myData); $bs->saveData(); }
-// file: saveMyData.php // some code to populate $myData $backupSolutions = array( new BackupToDisk('/tmp/backup') , new BackupToWebService('webserviceURL') ); foreach ( $backupSolutions as $bs ) { $bs->setData($myData); $bs->saveData(); }
-// file: saveMyData.php // some code to populate $myData $backupSolutions = array( new BackupToDisk('/tmp/backup') , new BackupToWebService('webserviceURL') ); foreach ( $backupSolutions as $bs ) { $bs->setData($myData); $bs->saveData(); }
вы правы, PHP не является сильным типизированным языком, мы никогда не говорили о том, что любой из ваших $ backupSolutions будет «MyBackupAbstract» или «MyBackupInterface», но это не помешает нам иметь характер полиморфизма, который отличается от функциональности те же методы.
__call()
и __callStatic()
должны поддерживать перегрузку метода. Подробнее об этом можно найти в руководстве . Или что именно вы после?
ОБНОВЛЕНИЕ: Я только что заметил другие ответы.
Для другого способа перегрузить метод, рассмотрите следующее:
<?php public function foo() { $args = func_get_arg(); }
Конечно, не очень, но это позволяет делать практически все, что вы хотите.
PHP имеет полиморфизм на основе классов, но не имеет формального механизма для реализации полиморфизма на основе аргументов.
Полиморфизм на основе классов означает, что вы можете мыслить в терминах базового класса, а вызываемые методы зависят от конечного класса. Например, если у вас есть массив объектов различных классов, таких как Triangle и Circle, и каждый из этих классов расширяет один и тот же класс Shape, вы можете рассматривать ваш массив как просто набор фигур. Вы можете прокручивать фигуры и вызывать метод getArea () каждой формы. Полиморфизм – это явление, при котором вызываемый метод getArea () зависит от класса объекта. Если ваша фигура является треугольником, вызывается Triangle :: getArea (), если Circle, то вызов Circle :: getArea () вызывается – даже если ваш код не различает круг и треугольник, но относится к каждому объекту как просто форму. Такая же строка кода приводит к выполнению другого блока кода в зависимости от класса объекта.
Полиморфизм, основанный на аргументах, является признаком некоторых строго типизированных языков, в которых несколько методов с одним и тем же именем могут быть определены в одном классе при условии, что они имеют разные параметры; то какой метод вызывается, зависит от предоставленных аргументов. Вы можете эмулировать полиморфизм на основе аргументов в слабо типизированных языках, таких как PHP, вручную рассматривая типы аргументов в вашем методе. Это то, что делает jQuery для реализации полиморфного API, несмотря на отсутствие у него естественного полиморфизма, основанного на аргументах.
Так что если «поддерживает полиморфизм» вы подразумеваете конкретно, что он обеспечивает формальный механизм для реализации полиморфизма на основе аргументов, ответ отрицательный. Для любого более широкого толкования ответ да. Разумеется, феномен полиморфизма на основе классов встречается на каждом объектно-ориентированном языке; и не имеет смысла для языка, который выполняет неявное преобразование типов для реализации полиморфизма на основе аргументов.
Вы все же можете переопределить методы, просто не перегружая их. Перегрузка (на C ++) – это то, где вы используете одно и то же имя метода для нескольких методов, отличающихся только числом и типами параметров. Это было бы сложно в PHP, так как оно слабо типизировано.
Переопределение – это то, где подкласс заменяет метод в базовом классе. На самом деле это основа полиморфизма, и вы можете сделать это на PHP.
Некоторые называют эту утиную печать .
PHP допускает полиморфный код, который генерирует ошибку компиляции на других языках. Простой иллюстрирует это. Первый код C ++, который генерирует ожидаемую ошибку компиляции:
class Base {}; class CommonDerivedBase { public: // The "= 0" makes the method and class abstract // virtual means polymorphic method virtual whoami() = 0; }; class DerivedBase : public CommonDerivedBase { public: void whoami() { cout << "I am DerivedBase \n"; } }; class Derived1 : public CommonDerivedBase { public: void whoami() { cout << "I am Derived1\n"; } }; class Derived2 : public CommonDerivedBase { public: void whoami() { cout << "I am Derived2\n"; } }; /* This will not compile */ void test_error(Base& db) { db.whoami(); }
Компилятор C ++ выдает это сообщение об ошибке для строки db.whoami()
error: no member named 'whoami' in 'Base'
потому что Base не имеет метода whoami (). Однако аналогичный PHP-код не находит таких ошибок до времени выполнения.
class Base {} abstract class DerivedCommonBase { abstract function whoami(); } class Derived1 extends DerivedCommonBase { public function whoami() { echo "I am Derived1\n"; } } class Derived2 extends DerivedCommonBase { public function whoami() { echo "I am Derived2\n"; } } /* In PHP, test(Base $b) does not give a runtime error, as long as the object * passed at run time derives from Base and implements whoami(). */ function test(Base $b) { $b->whoami(); } $b = new Base(); $d1 = new Derived1(); $d2 = new Derived2(); $a = array(); $a[] = $d1; $a[] = $d2; foreach($a as $x) { echo test($x); } test($d1); test($d2); test($b); //<-- A run time error will result.
Цикл foreach работает с выходом
I am Derived1 I am Derived2
Пока вы не вызовете тест ($ b) и не передадите экземпляр Base, вы получите ошибку времени выполнения. Таким образом, после выхода foreach , выход будет
I am Derived1 I am Derived2 PHP Fatal error: Call to undefined method Base::whoami() in home/kurt/public_html/spl/observer/test.php on line 22
Единственное, что вы можете сделать, чтобы сделать безопасным PHP, было бы добавить проверку времени выполнения, чтобы проверить, является ли $ b экземпляром класса, который вы намеревались.
function test(Base $b) { if ($b instanceof DerivedCommonBase) { $b->whoami(); } }
Но весь смысл полиморфизма заключается в том, чтобы исключить такие проверки времени выполнения.
Полиморфизм может быть реализован следующими способами:
method overriding
– обычный симпатичный был как указано выше
method overloading
Вы можете создать иллюзию перегрузки метода магическим методом __call ():
class Poly { function __call($method, $arguments) { if ($method == 'edit') { if (count($arguments) == 1) { return call_user_func_array(array($this,'edit1'), $arguments); } else if (count($arguments) == 2) { return call_user_func_array(array($this,'edit2'), $arguments); } } } function edit1($x) { echo "edit with (1) parameter"; } function edit2($x, $y) { echo "edit with (2) parameter"; } } $profile = new Poly(); $profile->edit(1); $profile->edit(1,2);
Expln:
1) Here we are utilizing the power of __call() of listening calls of non-available methods and 2) after knowing it who had called with their inputs diverting them to desired method
In php
мы фактически working under the hood
чтобы дать желаемое поведение и дать ощущение of method overloading
Для того, что я видел здесь, php не поддерживает полиморфизм и методы перегрузки. Вы можете взломать свой путь, чтобы фактически приблизиться к обеим функциональным возможностям, но они далеки от первоначальной цели. Многие из примеров здесь либо расширяют класс, либо создают хак для эмуляции полиморфизма.