Matthew Simon Cavalletto

NAME

Class::MakeMethods::Composite::Universal - Composite Method Tricks

SYNOPSIS

  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... 

DESCRIPTION

The Composite::Universal suclass of MakeMethods provides some generally-applicable types of methods based on Class::MakeMethods::Composite.

METHOD GENERATOR TYPES

patch

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} };
          }
        } 
      ],
    },
  );

make_patch

A convenient wrapper for make() and the patch method generator.

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} } 
    ]
  );

hook

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 ALSO

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.