Работа с несколькими наследуемыми конструкторами в Moose - PullRequest
6 голосов
/ 29 июня 2009

Привет,

Я изучаю Moose и пытаюсь написать подкласс CGI :: Application с Moose, что затрудняется тем, что CGI-App не основано на лося.

В других моих подклассах CGI-App мне нравится иметь родительский класс с методом setup, который просматривает таблицу символов дочернего класса и автоматически устанавливает режимы выполнения. Я полагаю, что могу использовать средства метакласса Moose, чтобы добиться того же самого более чистым способом. Итак, вот что я имею в своем родительском классе:

use MooseX::Declare;

class MyApp::CGI 
extends Moose::Object
extends CGI::Application { 

    method setup { 
        $self->start_mode( 'main' );

        my @methods = map { $_->name } $self->meta->get_all_methods;

        $self->run_modes( map  { /^rm_(.+)$/  => $_ }
                          grep { /^rm_/ }
                          @methods
                        );
    }

}

... и в моем детском классе:

use MooseX::Declare;

class MyApp::CGI::Login 
extends MyApp::CGI { 
    method rm_main { 
        return "it works";
    }
}

Я понял, что причина, по которой мои режимы выполнения не были настроены должным образом, заключается в том, что setup вызывается конструктором CGI-App, а Moose::Object вставляет свой собственный конструктор в мой класс. Я попытался решить эту проблему с помощью модификатора метода:

around new { 
    $self = $orig->( @_ );
    $self->CGI::Application::new( @_ );
}

Это дает мне

Can't call method "BUILDARGS" on unblessed reference at ...Moose/Object.pm line 21.

Однако у меня есть ощущение, что я поступаю об этом совершенно неверным образом, и у Муз есть гораздо лучшие возможности для достижения того, чего я хочу, чего я еще не обнаружил.

1 Ответ

9 голосов
/ 29 июня 2009

Вы уже просматривали Moose :: Cookbook :: Basics :: DateTime_ExtendingNonMooseParent и MooseX :: NonMoose ?

Обновление: Я не очень знаком с лосями и разными техниками. Я не смог собрать модули для компиляции, используя MooseX::Declare и MooseX::NonMoose вместе. Тем не менее, вот то, что, кажется, работает:

Базовый класс приложения

package My::App;

use Moose;
use MooseX::NonMoose;
extends 'CGI::Application';

sub setup {
    my $self = shift;
    $self->start_mode( 'main' );

    $self->run_modes(
        map { $_ = $_->name;
              /^rm_ (?<rm>.+) $/x ? ( $+{rm} => $_ ) : ()
        } $self->meta->get_all_methods
    );
}

"My::App"

Производный класс

package My::Login;
use Moose;
extends 'My::App';

sub rm_main { 'it works!' }

"My::Login"

Сценарий

#!/usr/bin/perl

use strict;
use warnings;

# For testing on the command line
use FindBin qw( $Bin );
use lib $Bin;

use My::Login;

my $app = My::Login->new;

$app->run;

выход

C:\Temp\f> t
Content-Type: text/html; charset=ISO-8859-1

it works!
...