};
}
+sub build_variant_package_name {
+ my ($me, $variable, @args) = @_;
+ if ($variable->can('make_variant_package_name')) {
+ return $variable->make_variant_package_name(@args);
+ }
+ return "${variable}::_Variant_".++$Variable{$variable}{anon};
+}
+
sub build_variant_of {
my ($me, $variable, @args) = @_;
- my $variant_name = "${variable}::_Variant_".++$Variable{$variable}{anon};
+ my $variant_name = $me->build_variant_package_name($variable, @args);
foreach my $to_import (@{$Variable{$variable}{args}{importing}}) {
my ($pkg, $args) = @$to_import;
require_module $pkg;
=head1 SYNOPSIS
+Creation of anonymous variants:
+
# declaring a variable Moo role
package My::VariableRole::ObjectAttr;
use strictures 1;
my $obj = My::Class::WithObjectAttr->new;
$obj->some_obj; # returns a Some::Class instance
+And the same thing, only with named variants:
+
+ # declaring a variable Moo role that can be named
+ package My::VariableRole::ObjectAttrNamed;
+ use strictures 1;
+ use Package::Variant importing => ['Moo::Role'],
+ subs => [ qw(has around before after with) ];
+ use Module::Runtime 'module_notional_filename'; # only if you need protection
+
+ # this method is run at variant creation time to determine its custom
+ # package name. it can use the arguments or do something entirely else.
+ sub make_variant_package_name {
+ my ($class, $package, %arguments) = @_;
+ $package = "Private::$package"; # you can munge the input here if you like
+ # only if you *need* protection
+ die "Won't clobber $package" if $INC{module_notional_filename $package};
+ return $package;
+ }
+
+ # same as in the example above, except for the argument list. in this example
+ # $package is the user input, and
+ # $target_package is the actual package in which the variant gets installed
+ sub make_variant {
+ my ($class, $target_package, $package, %arguments) = @_;
+ my $name = $arguments{name};
+ has $name => (is => 'lazy');
+ install "_build_${name}" => sub {return $arguments{class}->new};
+ }
+
+ # using the role
+ package My::Class::WithObjectAttr;
+ use strictures 1;
+ use Moo;
+ use My::VariableRole::ObjectAttrNamed;
+
+ # create the role under a specific name
+ ObjectAttrNamed "My::Role" => (name => 'some_obj', class => 'Some::Class');
+ # and use it
+ with "Private::My::Role";
+
+ # using our class
+ my $obj = My::Class::WithObjectAttr->new;
+ $obj->some_obj; # returns a Some::Class instance
+
=head1 DESCRIPTION
This module allows you to build a variable package that contains a package
This is a class method receiving the C<$target> package and the
C<@arguments> defining the requested variant.
+=head2 make_variant_package_name
+
+ Some::Variant::Package->make_variant_package_name( @arguments );
+
+B<You may optionally provide this method.> If present, this method will be
+used to determine the package name for a particular variant being constructed.
+
+If you do not implement it, a unique package name something like
+
+ Some::Variant::Package::_Variant_A003
+
+will be created for you.
+
=head2 import
use Some::Variant::Package;