2009-11-01 12 views
5

Si consideri il seguente:problema con mixins in un MooseX :: classe 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; 

... 

L'uscita quando questo viene compila:

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

Perché mi interessa? Perché quando provo a use una classe CGI :: Application :: Plugin :: *, mi aspetto che erediti da CGI::Application già in fase di compilazione. La classe plugin tenta di chiamare add_callback come metodo di classe sulla mia classe, ma non può, perché il mio @ISA non è ancora impostato.

Qual è il modo migliore per risolvere questo problema? Ottimizzare manualmente @ISA in un blocco BEGIN interferisce con MooseX::NonMoose?

Modifica

Il seguente sembra funzionare, ma trovo offensivo:

package MyApp::CGI; 

use Moose; 
use MooseX::NonMoose; 

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

io non ne so abbastanza (o qualsiasi cosa, in realtà) su interni Moose sapere se questo è una buona idea.

+5

BEGIN {extends ...}. – jrockway

+1

(Vale la pena notare che "utilizzare" come sinonimo di BEGIN è un antipattern comune.Vedi anche: "usa ok ...") – jrockway

+0

jrockway: che dovrebbe essere una risposta, non un commento – ysth

risposta

5

non trovo use base 'CGI::Application'; extends 'CGI::Application'; ad essere terribilmente orribile perché fa esattamente quello che vi serve:

  • a tempo di compilazione, @ISA contiene 'CGI::Application', che soddisfa esattamente i requisiti di utilizzo di CGI :: Application :: Plugin ::
  • In fase di esecuzione, la classe è un discendente , con tutti i vantaggi che ne derivano (essendo in grado di progettare la composizione della classe con Moosey meta bontà). È solo dopo che è stata rilevata la riga extends 'CGI::Application' che qualsiasi lavoro viene eseguito (i metodi vengono chiamati sulla classe) che si basano sul lavoro svolto dall'istruzione extends: la classe scende da Moose::Object e si dispone di una metagina installata.

Detto questo, la soluzione di jrockway dovrebbe funzionare anche:

BEGIN { extends 'CGI::Application' } 

... dove si ottiene tutto il meta bontà Moosey solo un po 'prima del previsto da quando ne avete bisogno, e non dovrebbe essere troppo prima del previsto, a patto di aver già chiamato use Moose e use MooseX::NonMoose per definire extends.

(Addendum:. Ora sto meditando le complessità complilational di creare la possibilità di forzare il parsing di una parola chiave a tempo di compilazione, che vengono analizzati immediatamente, come se fossero avvolte in un blocco BEGIN per esempio qualcosa come se Moose.pm ha dichiarato use compiletime qw(extends). Sarebbe un bel pezzo di zucchero sintattico di sicuro.)

+1

Utilizzare un blocco 'BEGIN' funziona. Darei il ++ a jrockaway ma non lo ha inserito in una risposta. :) – friedo

+1

Ether: Devel :: BeginLift lo fa. – jrockway

+0

@jrockway: ooh, nuovo giocattolo con cui giocare! Grazie! – Ether

Problemi correlati