Reputation: 52039
I've been playing around with this code:
package Foo;
use Moose;
package main;
my $PACKAGE = "Foo";
{
no strict 'refs';
my $has = *{"${PACKAGE}::has"}{CODE};
my $with = *{"${PACKAGE}::with"}{CODE};
# Add a instance member to class $PACKAGE
$has->("bar", is => "rw", required => 1);
# Add a role to class $PACKAGE
$with->("some::role");
}
# Create an instance of $PACKAGE:
$PACKAGE->new(); # error: attribute 'bar' is required means we were successful
This allows me to create a Moose class at run-time, i.e. add instance members to a class, add roles, etc.
My question is: how can I import Moose into package $PACKAGE
?
I know I can do this with eval: eval "package $PACKAGE; use Moose";
but I'm wondering if there is a solution along the lines of Moose->import(... $PACKAGE ...)
.
i.e., a way without using eval
. Or is there a completely different way of creating and modifying Moose classes at run time?
Upvotes: 3
Views: 2471
Reputation: 1923
You probably want to take a look at Moose::Meta::Class and its create
method:
my $class = Moose::Meta::Class->create('Foo',
attributes => [attr => Moose::Meta::Attribute->new(is => 'ro'), ...],
roles => [...],
methods => {...},
superclasses => [...],
);
# Edit: Adding an attribute and method modifiers:
$class->add_attribute(otherattr => (is => 'ro'));
$class->add_around_method_modifier(methodname => sub { ... });
Moose::Meta::Class
is a subclass of Class::MOP::Class, so you might want to peek into that one as well. With the above, you can specify roles, superclasses, attributes and methods, or you can first create and then add them via the MOP; whatever fits best.
For the attributes you'll want the Moose kind, which means Moose::Meta::Attribute objects. The constructor to that object is basically the same as using has
.
Upvotes: 19
Reputation: 385877
Call extends
, with
, has
, before
, after
, around
, override
and augment
in the Moose package instead of the ones exported by Moose, and pass the meta
object of the class you are creating as an additional first argument.
use strict;
use warnings;
use feature qw( say );
use Moose qw( );
{ # Create MyClass on the fly.
my $meta = Moose->init_meta( for_class => 'MyClass' );
# Moose::with( $meta, 'MyRole' );
Moose::has( $meta, foo => (
is => 'ro',
));
}
say MyClass->new( foo => "Foo" )->foo; # Foo
Upvotes: -5
Reputation: 1330
You may want to use Class::MOP, see for example https://metacpan.org/module/Moose::Manual::MOP#ALTERING-CLASSES-WITH-THE-MOP or https://metacpan.org/module/Class::MOP::Class#SYNOPSIS
Upvotes: 4