programming polimorfism oriented easy php oop programming-languages polymorphism

php - oriented - polimorfism



¿Es lo que parece polimorfismo en PHP realmente polimorfismo? (9)

Algunos llaman a este pato escribiendo .

Intentando averiguar si PHP admite características como la sobrecarga de métodos, la herencia y el polimorfismo, descubrí:

  • no soporta la sobrecarga de métodos
  • apoya la herencia

Pero no estoy seguro sobre el polimorfismo. Encontré este googlear en internet:

Debo tener en cuenta que en PHP el polimorfismo no es como debería ser. Quiero decir que sí funciona, pero como tenemos un tipo de datos débil, no es correcto.

Entonces, ¿es realmente polimorfismo?

Editar Simplemente no puedo colocar un SÍ o NO definitivo junto a PHP supports polymorphism . No me gustaría afirmar: "PHP no admite el polimorfismo", cuando en realidad lo hace. O viceversa.


El polimorfismo se puede implementar en los siguientes métodos:

  1. method overriding - normal bonito era como el anterior

  2. method overloading

Puedes crear una ilusión de sobrecarga de métodos con el método mágico __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);

Explotar

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 , en realidad estamos working under the hood para dar el comportamiento deseado y dar la sensación of method overloading


PHP permite código polimórfico que generaría un error de compilación en otros idiomas. Un simple ilustra esto. Primer código C ++ que genera un error de compilación esperado:

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(); }

El compilador de C ++ emitirá este mensaje de error para la línea db.whoami()

error: no member named ''whoami'' in ''Base''

porque Base no tiene un método llamado whoami (). Sin embargo, el código PHP análogo no encuentra tales errores hasta el tiempo de ejecución.

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.

El bucle foreach funciona con la salida.

I am Derived1 I am Derived2

No hasta que llame a prueba ($ b) y pase una instancia de Base, obtendrá un error de tiempo de ejecución. Así que después del foreach , la salida será

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

Lo único que puede hacer para hacer que PHP sea más seguro sería agregar una verificación de tiempo de ejecución para probar si $ b es una instancia de la clase que deseaba.

function test(Base $b) { if ($b instanceof DerivedCommonBase) { $b->whoami(); } }

Pero el punto central del polimorfismo es eliminar tales controles de tiempo de ejecución.


PHP tiene un polimorfismo basado en clases, pero carece de un mecanismo formal para implementar un polimorfismo basado en argumentos.

El polimorfismo basado en clase significa que puedes pensar en términos de una clase base y que los métodos a los que se llama dependen de la clase final. Por ejemplo, si tiene una matriz de objetos de varias clases, como Triángulo y Círculo, y cada una de estas clases extiende la misma clase de Forma, puede considerar su matriz como una mera colección de formas. Puede recorrer las formas y llamar al método getArea () de cada forma. El polimorfismo es el fenómeno por el cual se llama al método getArea () dependiendo de la clase del objeto. Si su forma es un Triángulo, se llama a Triangle :: getArea (), si se llama a un Círculo, entonces se llama a Circle :: getArea (), aunque su código no distingue entre un Círculo y un Triángulo, pero considera a cada objeto como simplemente una forma. La misma línea de código da como resultado que se ejecuta un bloque de código diferente, dependiendo de la clase del objeto.

El polimorfismo basado en argumentos es una característica de algunos lenguajes tipográficos, en los que se pueden definir múltiples métodos con el mismo nombre en una sola clase, siempre que tengan diferentes parámetros; entonces el método que se llama depende de los argumentos proporcionados. Puede emular el polimorfismo basado en argumentos en lenguajes de tipos débiles como PHP, considerando manualmente los tipos de argumentos dentro de su método. Esto es lo que hace jQuery para implementar una API polimórfica a pesar de la falta de polimorfismo nativo basado en argumentos de JavaScript.

Por lo tanto, si "apoya el polimorfismo" quiere decir específicamente que proporciona un mecanismo formal para implementar el polimorfismo basado en argumentos, la respuesta es no. Para una interpretación más amplia, la respuesta es sí. Es lógico que el fenómeno del polimorfismo basado en clases ocurra en todos los lenguajes orientados a objetos; y no tiene sentido que un lenguaje que realice una conversión de tipo implícita implemente un polimorfismo basado en argumentos.


Por lo que he visto aquí, php no admite polimorfismo ni métodos de sobrecarga. Puedes hackear tu camino para realmente acercarte a estas dos funcionalidades de OOP, pero están lejos de su propósito original. Muchos de los ejemplos aquí están extendiendo una clase o creando un truco para emular el polimorfismo.


Todavía puede anular los métodos, pero no sobrecargarlos. La sobrecarga (en C ++) es donde se usa el mismo nombre de método para múltiples métodos, diferenciándose solo en número y tipos de parámetros. Esto sería difícil en PHP ya que es de tipo débil.

La anulación es donde la subclase reemplaza un método en la clase base. Que es realmente la base para el polimorfismo, y puedes hacerlo en PHP.


aunque PHP no admite la sobrecarga de métodos como lo ha experimentado en otros idiomas, digamos Java. pero PUEDE tener una sobrecarga de métodos en PHP, pero el método de definición es diferente. Si desea tener una funcionalidad diferente para un método determinado, con un conjunto diferente de parámetros en PHP, puede hacer algo como esto:

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 } }

Podría haber una implementación más limpia, pero esto es solo una muestra.

PHP soporta herencia e interfaces. Así que puedes tener polimorfismo usándolos. Puedes tener una interfaz como esta:

// 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); } }

ahora en tu aplicación, puedes usarlo así:

// 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(); }

tiene razón, PHP no es un lenguaje fuerte, nunca mencionamos que cualquiera de sus $ backupSolutions sería un ''MyBackupAbstract'' o ''MyBackupInterface'', pero eso no nos impediría tener la naturaleza del polimorfismo, que es una funcionalidad diferente a la de usar mismos metodos


__call() y __callStatic() deben admitir la sobrecarga de métodos. Más sobre esto está disponible en el manual . ¿O qué es exactamente lo que estás buscando?

ACTUALIZACIÓN: Acabo de notar las otras respuestas.

Para otra forma de sobrecargar un método, considere lo siguiente:

<?php public function foo() { $args = func_get_arg(); }

Ciertamente no es bonito, pero te permite hacer virtualmente lo que quieras.


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>''; }

Puedes etiquetarlo todo lo que quieras, pero eso me parece un polimorfismo.