2009-11-01 5 views
5

considerar lo siguiente:Problema con mixins en una clase MooseX :: NonMoose

package MyApp::CGI; 

use Moose; 
use MooseX::NonMoose; 
use Data::Dumper; 

extends 'CGI::Application'; 

BEGIN { 
    print "begin isa = " . Dumper \@MyApp::CGI::ISA; 
}; 

print "runtime isa = " . Dumper \@MyApp::CGI::ISA; 

... 

La salida cuando este se compila:

begin isa = $VAR1 = [ 
      'Moose::Object' 
     ]; 
runtime isa = $VAR1 = [ 
      'CGI::Application', 
      'Moose::Object' 
     ]; 

por qué me importa? Porque cuando intento use una clase CGI :: Application :: Plugin :: *, espera que herede de CGI::Application en tiempo de compilación. La clase de complemento intenta llamar al add_callback como un método de clase en mi clase, pero no puede, porque mi @ISA aún no está configurado.

¿Cuál es la mejor manera de resolver esto? ¿Ajustar manualmente @ISA en un bloque BEGIN interferir con MooseX::NonMoose?

Editar

El siguiente parece funcionar, pero me resulta ofensiva:

package MyApp::CGI; 

use Moose; 
use MooseX::NonMoose; 

use base 'CGI::Application'; 
extends 'CGI::Application'; 

No sé lo suficiente (o nada, en realidad) sobre el funcionamiento interno de los alces saber si esto es una buena idea.

+5

BEGIN {extends ...}. – jrockway

+1

(Vale la pena señalar que "usar" como sinónimo de BEGIN es un antipatín común. Ver también: "usar bien ...") – jrockway

+0

jrockway: debería ser una respuesta, no un comentario – ysth

Respuesta

5

no encuentro use base 'CGI::Application'; extends 'CGI::Application'; a ser terriblemente espantosa, ya que hace exactamente lo que necesita:

  • en tiempo de compilación, @ISA contiene 'CGI::Application', que satisface exactamente los requisitos de uso de CGI :: Application :: Plugin :: *
  • En tiempo de ejecución, su clase es un descendiente Moose de CGI::Application, con todos los beneficios consiguientes (pudiendo diseñar la composición de su clase con la bondad meta de Moosey). Solo después de encontrar la línea extends 'CGI::Application' se realiza cualquier trabajo (es decir, se invocan métodos en su clase) que se basan en el trabajo realizado por la declaración extends: que su clase desciende de Moose::Object y tiene una metaclase instalada.

Dicho esto, la solución de jrockway también debería funcionar:

BEGIN { extends 'CGI::Application' } 

... donde se obtiene toda la bondad meta Moosey sólo un poco antes de lo previsto desde el momento en que lo necesite, y no debe ser también antes de lo previsto, siempre que ya haya llamado use Moose y use MooseX::NonMoose para definir extends.

(Adición:. Ahora estoy ponderando las complejidades complilational de la creación de la capacidad de forzar el análisis de una palabra clave en tiempo de compilación que se analizan de inmediato, como si estuvieran envueltos en un bloque BEGIN por ejemplo, algo así como si Moose.pm declaró use compiletime qw(extends). Sería una buena pieza de azúcar sintáctico seguro.)

+1

Usar un bloque 'BEGIN' funciona. Le daría ++ a Jrockaway pero no lo publicó en una respuesta. :) – friedo

+1

Ether: Devel :: BeginLift hace eso. – jrockway

+0

@jrockway: ooh, ¡juguete nuevo para jugar! ¡Gracias! – Ether