2011-03-01 14 views
7

¿Hay alguna manera en php para escribir sugerencias para dos interfaces diferentes, no relacionadas? Por ejemplo:Tipo Sugerencia para múltiples interfaces no relacionadas

interface errorable { 
    function error($msg); 
} 

interface recordable { 
    ssh_for_recorder(); 
} 

class uploader__module extends base__module implements errorable, recordable { 
    public function ssh_for_recorder() { 
     return new ssh2; 
    } 
    public function error($msg) { 
     $this->errors[] = $msg; 
    } 

    public function upload() { 
     $recorder = new recorder($this); 
     $recorder->run(); 
    } 
} 

class recorder { 
    private $ssh2; 
    private $module; 
    private function upload() { 
     if (!$this->ssh2) { 
     $this->module->error("No SSH2 connection"); 
     } 
    } 
    public function __construct({recordable,errorable} $module) { 
     $this->module = $module; 
     $this->ssh2 = $module->ssh_for_recorder(); 
    } 
} 

Como se puede ver en el código anterior, la clase grabador espera que su módulo de tener la capacidad de ejecutar tanto error() y ssh_for_recorder(), pero estos son definidos por diferentes interfaces. errorable no necesita ser registrable y viceversa tampoco.

¿Existe una mejor práctica para hacer esto? Estaba pensando en crear una interfaz que se extienda desde grabable y errorable y tener upload__module implementar eso, pero no sé cómo llamarlo.

+0

¿Qué tiene esto que ver con el tipo de alusión? – Hamish

+1

Ver el constructor de la grabadora. Quiero escribir una sugerencia tanto grabable como errorable. –

+0

Creo que @Hammish se está confundiendo, la sugerencia de tipo en PHP requiere que una clase sea de cierto tipo, donde @tandu requiere que se comprueben varios tipos de interfaces. – RobertPitt

Respuesta

10

No, esto no es posible en php.

Hay otros idiomas (principalmente funcionales) que admiten esta función que se llama tipo de unión (http://en.wikipedia.org/wiki/Sum_type).

+0

¿Cómo sugeriría solucionar esto en PHP? –

+0

Bueno, crea una nueva interfaz que se extiende tanto grabable como errorable. Sin embargo, tendrá que cambiar las clases que implementan ambas interfaces para implementar la nueva interfaz. – linepogl

+0

Como yo pensaba. Terminé teniendo extensible extensible grabable así que funcionó también en mi aplicación. –

6

El único truco dentro de PHP es una función de ayuda para hacer los cheques por usted dentro del método de esta manera:

function CheckInterfaces($object,array $interfaces) 
{ 
    foreach($interfaces as $i) 
    { 
     if(!is_a($object,$i)) 
     { 
      return false; 
     } 
    } 
    return true; 
} 

Y luego en el método de hacer:

public function Something($object) 
{ 
    if(CheckInterfaces($object,array("foo","bar"))) 
    { 
     throw new ArgumentException(gat_class($object) . " Must be a member of foo,bar to be passed to Something"); 
    } 
} 

otro método alrededor de este ius tema para crear una interfaz de unión para sus interfaces necesarias, heres ejemplo rápido

interface foobar extends foo,bar{} 

entonces solo puede requerir foobar para el método.

+1

# 1 es interesante, pero creo que va demasiado lejos. Prefiero # 2. Solo una nota, sin embargo, las interfaces extienden otras interfaces, no las implementan. Su código causará un error de sintaxis. –

+0

Pequeña supervisión allí. – RobertPitt

+1

Aunque es la única solución razonable, no me gusta 2 porque también tengo que cambiar la clase para implementar la interfaz de unión, en lugar de las interfaces por separado – bencoder

0
public function __construct(recordable $recordable_module, errorable $errorable_module) { 

    if($recordable_module == $errorable_module){ 
    $module = $recordable_module; 
    } 
    $this->module = $module; 
    $this->ssh2 = $module->ssh_for_recorder(); 
} 
2

he decidido responder a esta pregunta, aunque ya ha aceptado una respuesta sobre la base de que ninguna de las respuestas dadas son muy aceptables. Si bien la respuesta aceptada es técnicamente correcta, hay una forma de evitarla. En cuanto a las otras respuestas, sus soluciones son poco elegantes y no del todo satisfactorias.

PHP soporta una característica bastante oscura que permite que una interfaz herede de otra, y de hecho una interfaz es capaz de heredar desde múltiples interfaces base.

Por ejemplo, el siguiente es perfectamente válido:

interface iFoo 
{ 
    public function doFoo(); 
} 

interface iBar 
{ 
    public function doBar(); 
} 

interface iBaz extends iFoo, iBar 
{ 
    // This interface implicitly has all the methods of iFoo and iBar 
} 

punto de vista semántico, si quieres un método/función para aceptar sólo un argumento que implementa varias interfaces a continuación, que tendería a sugerir que se espera que las clases que implementar el mismo conjunto de interfaces múltiples debería de hecho implementar una interfaz que cubra las dos interfaces a las que quiere que se ajuste su argumento.

En su caso si usted quiere algo que es a la vez un errorable y una grabación sólo tendrá que añadir la siguiente interfaz:

interface RecordableErrorable extends Recordable, Errorable { } 

Y a continuación, el constructor de la clase registrador sería simplemente esperar que la interfaz como su argumento

public function __construct(RecordableErrorable $module) { } 

Un posible punto de fricción podría ser si grabables y Errorable tanto implementan métodos con el mismo nombre. Habría un enfrentamiento allí que necesitaría resolverse.Creo que hay mecanismos en PHP para manejar ese caso, aunque no pude decirle cuáles son.

Cuestiones relacionadas