Jesse Luehrs > Moose-2.0604 > Moose::Cookbook::Meta::GlobRef_InstanceMetaclass

Download:
Moose-2.0604.tar.gz

Annotate this POD

CPAN RT

New  11
Open  40
Stalled  4
View/Report Bugs
Source   Latest Release: Moose-2.1205

NAME ^

Moose::Cookbook::Meta::GlobRef_InstanceMetaclass - Creating a glob reference meta-instance class

VERSION ^

version 2.0604

SYNOPSIS ^

  package My::Meta::Instance;

  use Scalar::Util qw( weaken );
  use Symbol qw( gensym );

  use Moose;
  extends 'Moose::Meta::Instance';

  sub create_instance {
      my $self = shift;
      my $sym = gensym();
      bless $sym, $self->_class_name;
  }

  sub clone_instance {
      my ( $self, $instance ) = @_;

      my $new_sym = gensym();
      %{*$new_sym} = %{*$instance};

      bless $new_sym, $self->_class_name;
  }

  sub get_slot_value {
      my ( $self, $instance, $slot_name ) = @_;
      return *$instance->{$slot_name};
  }

  sub set_slot_value {
      my ( $self, $instance, $slot_name, $value ) = @_;
      *$instance->{$slot_name} = $value;
  }

  sub deinitialize_slot {
      my ( $self, $instance, $slot_name ) = @_;
      delete *$instance->{$slot_name};
  }

  sub is_slot_initialized {
      my ( $self, $instance, $slot_name ) = @_;
      exists *$instance->{$slot_name};
  }

  sub weaken_slot_value {
      my ( $self, $instance, $slot_name ) = @_;
      weaken *$instance->{$slot_name};
  }

  sub inline_create_instance {
      my ( $self, $class_variable ) = @_;
      return 'do { my $sym = Symbol::gensym(); bless $sym, ' . $class_variable . ' }';
  }

  sub inline_slot_access {
      my ( $self, $instance, $slot_name ) = @_;
      return '*{' . $instance . '}->{' . $slot_name . '}';
  }

  package MyApp::User;

  use metaclass 'Moose::Meta::Class' =>
      ( instance_metaclass => 'My::Meta::Instance' );

  use Moose;

  has 'name' => (
      is  => 'rw',
      isa => 'Str',
  );

  has 'email' => (
      is  => 'rw',
      isa => 'Str',
  );

DESCRIPTION ^

This recipe shows how to build your own meta-instance. The meta instance is the metaclass that creates object instances and helps manages access to attribute slots.

In this example, we're creating a meta-instance that is based on a glob reference rather than a hash reference. This example is largely based on the Piotr Roszatycki's MooseX::GlobRef module.

Our class is a subclass of Moose::Meta::Instance, which creates hash reference based objects. We need to override all the methods which make assumptions about the object's data structure.

The first method we override is create_instance:

  sub create_instance {
      my $self = shift;
      my $sym = gensym();
      bless $sym, $self->_class_name;
  }

This returns an glob reference which has been blessed into our meta-instance's associated class.

We also override clone_instance to create a new array reference:

  sub clone_instance {
      my ( $self, $instance ) = @_;

      my $new_sym = gensym();
      %{*$new_sym} = %{*$instance};

      bless $new_sym, $self->_class_name;
  }

After that, we have a series of methods which mediate access to the object's slots (attributes are stored in "slots"). In the default instance class, these expect the object to be a hash reference, but we need to change this to expect a glob reference instead.

  sub get_slot_value {
      my ( $self, $instance, $slot_name ) = @_;
      *$instance->{$slot_name};
  }

This level of indirection probably makes our instance class slower than the default. However, when attribute access is inlined, this lookup will be cached:

  sub inline_slot_access {
      my ( $self, $instance, $slot_name ) = @_;
      return '*{' . $instance . '}->{' . $slot_name . '}';
  }

The code snippet that the inline_slot_access method returns will get eval'd once per attribute.

Finally, we use this meta-instance in our MyApp::User class:

  use metaclass 'Moose::Meta::Class' =>
      ( instance_metaclass => 'My::Meta::Instance' );

We actually don't recommend the use of metaclass in most cases. However, the other ways of using alternate metaclasses are more complex, and would complicate our example code unnecessarily.

CONCLUSION ^

This recipe shows how to create your own meta-instance class. It's unlikely that you'll need to do this yourself, but it's interesting to take a peek at how Moose works under the hood.

SEE ALSO ^

There are a few meta-instance class extensions on CPAN:

AUTHOR ^

Moose is maintained by the Moose Cabal, along with the help of many contributors. See "CABAL" in Moose and "CONTRIBUTORS" in Moose for details.

COPYRIGHT AND LICENSE ^

This software is copyright (c) 2012 by Infinity Interactive, Inc..

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

syntax highlighting: