18/05/2014, 14:35
|
| Colaborador | | Fecha de Ingreso: mayo-2012 Ubicación: Somewhere
Mensajes: 1.332
Antigüedad: 12 años, 6 meses Puntos: 320 | |
Respuesta: APORTE: Emular polimorfismo y sobrecarga tipada de forma simple. Bueno, veo que hubo varias sugerencias y criticas constructivas sobre esto, asi que aqui publico la nueva version que contempla todo lo que se planteo, y ademas, esta optimizada en comparacion a la anterior, la van a encontrar bastante flexible, aqui esta:
Código PHP:
Ver original<?php namespace NS; class OverridableType extends \ReflectionObject { private $overload = array(); private static $overloadStatic = array(); public function __construct() { parent::__construct($this); foreach ($this->getMethods() as $method) { { return ($filter ? explode(" ", $filter) : null); }, explode("\n", $method->getDocComment()))); if($info) { foreach($info as $directive) { switch($directive[0]) { case "@overload" : $tmp["method"] = $directive[1]; break; case "@count" : $tmp["count"] = $directive[1]; break; case "@param" : $tmp["params"][] = strtolower($directive[1]); break; case "@default" : $tmp["default"] = $directive[1]; break; } } if($method->isStatic()) { if($tmp["default"]) { if($tmp["count"]) self::$overloadStatic[get_called_class()][$tmp["method"]][$tmp["count"]]["default"] = $tmp["default"]; else self::$overloadStatic[get_called_class()][$tmp["method"]]["default"] = $tmp["default"]; } else self::$overloadStatic[get_called_class ()][$tmp["method"]][$tmp["count"]][] = array("types" => $tmp["params"], "name" => $method->getShortName()); } else { if($tmp["default"]) { if($tmp["count"]) $this->overload[$tmp["method"]][$tmp["count"]]["default"] = $tmp["default"]; else $this->overload[$tmp["method"]]["default"] = $tmp["default"]; } else $this->overload[$tmp["method"]][$tmp["count"]][] = array("types" => $tmp["params"], "name" => $method->getShortName()); } } } } private static function getNameOverload($name, $args, $map) { { if(isset($map[$name][$cant])) { foreach($map[$name][$cant] as $nro => $method) { if($nro !== "default") { $match = true; foreach($method["types"] as $tnro => $type) { if(!($argType == $type) and !($argType == 'object' && ($args[$tnro] instanceof $type))) { $match = false; break; } } if($match) return $method["name"]; } } if(isset($map[$name][$cant]["default"])) return $map[$name][$cant]["default"]; else die("No se pudo resolver el metodo $name con $cant argumentos tipados ".implode(", ",array_map(function($val) { return gettype($val); }, $args))."."); } elseif(isset($map["default"])) return $map["default"]; else die("No se pudo resolver el metodo $name con $cant argumentos."); } else die("No se pudo resolver el metodo $name."); } function __call($name, $args) { } function __callStatic($name, $args) { return forward_static_call([$this, self::getNameOverload($name, $args, self::$overloadStatic[get_called_class()])], $args); } } // Y asi es como se implementa. interface Vehicle { function run(); } namespace NSA; class Train implements \NS\Vehicle { function run() { echo 'chu-chua, chu-chua, chu-chua, ...<br />'; } } namespace NSB; class Train implements \NS\Vehicle { function run() { echo 'chu-chub, chu-chub, chu-chub, ...<br />'; } } namespace NS; class Car implements Vehicle { function run() { echo 'run, run, run, run, ...<br />'; } } class Moto implements Vehicle { function run() { echo 'rrrrrrrrrrrrrrrrrrrr ...<br />'; } } class Foto { function sepia() { echo 'me volvi sepia...<br />'; } } class Test extends OverridableType { /** @overload miMetodo @count 0 */ public static function smethod() { echo("<br>Hola, no has ingresado nada de forma estatica<br>"); } /** @overload miMetodo @count 1 @param integer */ public static function smethod1() { echo("<br>Hola, has ingresado: $unNumero estaticamente<br>"); } /** @overload miMetodo @count 0 */ public function method() { echo("<br>Hola, no has ingresado nada<br>"); } /** @overload miMetodo @count 1 @param integer */ public function method1($unNumero) { echo("<br>Hola, has ingresado: $unNumero<br>"); } /** @overload miMetodo @count 1 @param string */ public function method2($miString) { echo("<br>Hola, has ingresado: '$miString'<br>"); } /** @overload miMetodo @count 1 @param Train */ public function method3($unTren) { echo("<br>Hola, gracias por el tren<br>"); $unTren->run(); } /** @overload miMetodo @count 1 @param NSA\Train */ public function method3a($unTren) { echo("<br>Hola, gracias por el tren del namespace a<br>"); $unTren->run(); } /** @overload miMetodo @count 1 @param NSB\Train */ public function method3b($unTren) { echo("<br>Hola, gracias por el tren del namespace b<br>"); $unTren->run(); } /** @overload miMetodo @count 1 @param NS\Car */ public function method4($unAuto) { echo("<br>Hola, gracias por el auto<br>"); $unAuto->run(); } /** @overload miMetodo @count 1 @param NS\Vehicle */ public function method5($unVehiculo) { echo("<br>Hola, gracias por el vehiculo<br>"); $unVehiculo->run(); } /** @overload miMetodo @count 1 @param Object */ public function method6($unObjeto) { echo("<br>Hola, me diste un objeto: ".get_class($unObjeto).", muchas gracias.<br>"); } /** @overload miMetodo @count 2 @param integer @param string */ public function method7($unNumero, $miString) { echo("<br>Hola, has ingresado un numero: $unNumero y un string '$miString'<br>"); } /** @overload miMetodo @count 2 @param string @param integer */ public function method8($miString, $unNumero) { echo("<br>Hola, has ingresado un string: '$miString' y un numero $unNumero<br>"); } /** @overload miMetodo @count 2 @param integer @param integer */ public function method9($unNumero, $otroNumero) { echo("<br>Hola, has ingresado un numero: $unNumero y un numero $otroNumero<br>"); } } class Testb extends Test { /** @overload miMetodo @count 2 @param string @param integer */ public function method8($miString, $unNumero) { echo("<br>Hola, has ingresado un string: '$miString' y un numero $unNumero pero en una subclase.<br>"); } } $test = new Test; $test->miMetodo(); $test->miMetodo(1); $test::miMetodo(); $test::miMetodo(1); $test->miMetodo('hola'); $test->miMetodo(99, 'hola'); $test->miMetodo('hola', 1); $test->miMetodo(1, 2); $test->miMetodo(new Car); $test->miMetodo(new \NSA\Train); $test->miMetodo(new \NSB\Train); $test->miMetodo(new Moto); $test->miMetodo(new Foto); $testb = new Testb; $testb->miMetodo('hola', 1);
produce esta salida: Cita:
Hola, no has ingresado nada
Hola, has ingresado: 1
Hola, has ingresado: 'hola'
Hola, has ingresado un numero: 99 y un string 'hola'
Hola, has ingresado un string: 'hola' y un numero 1
Hola, has ingresado un numero: 1 y un numero 2
Hola, gracias por el auto
run, run, run, run, ...
Hola, gracias por el tren del namespace a
chu-chua, chu-chua, chu-chua, ...
Hola, gracias por el tren del namespace b
chu-chub, chu-chub, chu-chub, ...
Hola, gracias por el vehiculo
rrrrrrrrrrrrrrrrrrrr ...
Hola, me diste un objeto: NS\Foto, muchas gracias.
Hola, has ingresado un string: 'hola' y un numero 1 pero en una subclase.
__________________ Maratón de desafíos PHP Junio - Agosto 2015 en FDW | Reglamento - Desafios |