2009-11-01 14 views
5

Beachten Sie Folgendes:Problem Mixins in einem MooseX :: NonMoose Klasse

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; 

... 

Der Ausgang, wenn dieser kompiliert wird:

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

Warum interessieren sich ich? Weil, wenn ich use eine CGI :: Application :: Plugin :: * Klasse versuche, erwartet es mich von zur Kompilierzeit bereits erben. Die Plugin-Klasse versucht, add_callback als Klassenmethode für meine Klasse aufzurufen, kann dies aber nicht, da meine @ISA noch nicht eingerichtet ist.

Was ist der beste Weg, dies zu lösen? Würde @ISA manuell in einem BEGIN Block zwicken MooseX::NonMoose interferieren?

bearbeiten

Die folgende scheint zu funktionieren, aber ich finde es beleidigend:

package MyApp::CGI; 

use Moose; 
use MooseX::NonMoose; 

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

Ich weiß nicht genug (oder irgendetwas, wirklich) über Moose Interna zu wissen, ob dies ist eine gute Idee.

+5

BEGIN {erweitert ...}. – jrockway

+1

(Beachten Sie, dass "verwenden" als Synonym für BEGIN ist eine gemeinsame Antipattern. Siehe auch: "use ok ...") – jrockway

+0

jrockway: das sollte eine Antwort sein, kein Kommentar – ysth

Antwort

5

ich nicht use base 'CGI::Application'; extends 'CGI::Application'; finden furchtbar grässlich zu sein, weil es tut genau das, was Sie brauchen:

  • zur Compile-Zeit, @ISA enthält 'CGI::Application', die genau die Nutzungsanforderungen von CGI erfüllt :: Anwendung :: Plugin :: *
  • Zur Laufzeit ist Ihre Klasse ein Moose Nachkomme von CGI::Application, mit allen folgenden Vorteilen (in der Lage, die Zusammensetzung Ihrer Klasse mit Moosey Meta-Güte zu gestalten). Erst nachdem die Zeile extends 'CGI::Application' angetroffen wird, wird jede Arbeit erledigt (d. H. Methoden werden in Ihrer Klasse aufgerufen), die auf der von der extends-Anweisung ausgeführten Arbeit beruhen: Ihre Klasse stammt von Moose::Object ab und Sie haben eine Meta-Klasse installiert.

Das heißt, jrockway-Lösung sollte auch funktionieren:

BEGIN { extends 'CGI::Application' } 

... wo Sie die Moosey Meta alle Güte erhalten nur ein wenig früher als geplant aus, wenn Sie es brauchen, und es sollte nicht be auch vor dem Zeitplan, vorausgesetzt Sie haben bereits use Moose und use MooseX::NonMoose genannt, um extends zu definieren.

(Nachtrag:. Jetzt bin ich grübeln die complilational Komplexitäten die Fähigkeit der Erstellung der Analyse eines Stichwortes zur Compile-Zeit zu zwingen, die sofort so analysiert werden, als ob sie in einem BEGIN Block gewickelt wurden zum Beispiel so etwas wie wenn Moose.pm erklärte use compiletime qw(extends).Es wäre ein schönes Stück von syntaktischen Zucker sicher.)

+1

Verwenden Sie eine 'BEGIN' Block funktioniert. Ich würde jrockaway das ++ geben, aber er hat es nicht in einer Antwort gepostet. :) – friedo

+1

Ether: Devel :: BeginLift tut das. – jrockway

+0

@jrockway: Ooh, neues Spielzeug zum Spielen! Vielen Dank! – Ether