I want my OO module to be used in either 'classic' or 'modern' mode. Users type either of the 2:
use Foo; use Foo ':modern';
Some methods behave slightly differently depending on the package-scoped lexical boolean flag. When it is not too cumbersome or performance critical, the flag is checked inside a method, perhaps in a few places. Otherwise, methods are redefined, which, sadly, leads to code duplication. Additionally, in modern mode some constants are exported to the user, so they can use them. "Classic" users don't know nor care about these constants. Here is my implementation, is it OK or can be done better?
package Foo; use strict; use warnings; use feature 'say'; use parent 'Exporter'; my $MODE = 0; my %const; BEGIN { %const = ( ABC => 'abc', XYZ => 'xyz', # etc. # longer list ) } use constant \%const; our @EXPORT_OK = keys %const; sub import { my ( $self, $flag ) = @_; if ( defined $flag and $flag eq ':modern' ) { $MODE = 1; Foo-> export_to_level( 1, 'Foo', keys %const ); no warnings 'redefine'; *Foo::m2 = \&Foo::Modern::m2; # etc. # longer list } } sub new { my $class = shift; bless {}, $class } sub m1 { say $MODE ? 'modern 1' : 'classic 1' } sub m2 { say 'classic 2' } package Foo::Modern { sub m2 { say 'modern 2' } }; 1;
And a user does:
use strict; use warnings; use feature 'say'; use lib '.'; use Foo ':modern'; my $obj = Foo->new; $obj->m1; $obj->m2; say ABC;
In reply to Conditional and opt-in breaking change: is this design viable and my use of 'import' OK? by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |