Class::MakeMethods::Composite::Universal - Composite Method Tricks
package MyClass; use Class::MakeMethods::Composite::Universal ( hook => 'init', ); sub new { my $package = shift; my $self = bless {}, $package; $self->init(); return $self; } MyClass-> package MySubClass; @ISA = 'MyClass'; ... MyClass->foo( 'Foozle' ); print MyClass->foo(); MyClass->my_list(0 => 'Foozle', 1 => 'Bang!'); print MyClass->my_list(1); MyClass->my_index('broccoli' => 'Blah!', 'foo' => 'Fiddle'); print MyClass->my_index('foo'); ... my $obj = MyClass->new(...); print $obj->foo(); # all instances default to same value $obj->foo( 'Foible' ); # until you set a value for an instance print $obj->foo(); # it now has its own value print MySubClass->foo(); # intially same as superclass MySubClass->foo('Foobar'); # but overridable per subclass print $subclass_obj->foo(); # and shared by its instances $subclass_obj->foo('Fosil');# until you override them...
The Composite::Universal suclass of MakeMethods provides some generally-applicable types of methods based on Class::MakeMethods::Composite.
The patch ruleset generates composites whose core behavior is based on an existing subroutine.
Here's an sample usage:
sub foo { my $count = shift; return 'foo' x $count; } Class::MakeMethods::Composite::Universal->make( -ForceInstall => 1, patch => { name => 'foo', pre_rules => [ sub { my $method = pop @_; if ( ! scalar @_ ) { @{ $method->{args} } = ( 2 ); } }, sub { my $method = pop @_; my $count = shift; if ( $count > 99 ) { Carp::confess "Won't foo '$count' -- that's too many!" } }, ], post_rules => [ sub { my $method = pop @_; if ( ref $method->{result} eq 'SCALAR' ) { ${ $method->{result} } =~ s/oof/oozle-f/g; } elsif ( ref $method->{result} eq 'ARRAY' ) { map { s/oof/oozle-f/g } @{ $method->{result} }; } } ], }, );
A convenient wrapper for make() and the patch method generator.
make()
patch
Provides the '-ForceInstall' flag, which is required to ensure that the patched subroutine replaces the original.
For example, one could add logging to an existing method as follows:
Class::MakeMethods::Composite::Universal->make_patch( -TargetClass => 'SomeClassOverYonder', name => 'foo', pre_rules => [ sub { my $method = pop; warn "Arguments:", @_ } ] post_rules => [ sub { my $method = pop; warn "Result:", $method->{result} } ] );
External interface is normal; internally calls array of fragments. Among other things, this should allow meta-methods to individually provide "on init" or "on destroy" code.
How do you add to the hook? Pre/post, or arbitrary order? Ability to remove/replace specifc ones? Assign name? Loop in name order?
package MyWidget; use C::MM::Composite ( hook => 'init', ); sub new { my $widget = ...; $widget->init(); return $widget; } MyWidget->_hook_method('init', 'post+' => sub { (shift)->{count} ||= 3 }, );
NOTE: THIS METHOD GENERATOR IS INCOMPLETE.
The _hook_method interface, or an improvement thereto, needs to be added.
Hook methods should call up the inheritance tree.
See Class::MakeMethods and Class::MakeMethods::Composite for an overview of the method-generation framework this is based on.
See Class::MakeMethods::Guide for a getting-started guide, annotated examples of usage, and a listing of the method generation classes included in this distribution.
See Class::MakeMethods::ReadMe for distribution, installation, version and support information.
To install Class::MakeMethods, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Class::MakeMethods
CPAN shell
perl -MCPAN -e shell install Class::MakeMethods
For more information on module installation, please visit the detailed CPAN module installation guide.