more
[gitmo/Class-MOP.git] / examples / LazyClass.pod
CommitLineData
4300f56a 1
046688ed 2package # hide the package from PAUSE
3 LazyClass;
4300f56a 4
5use strict;
6use warnings;
7
99e5b7e8 8our $VERSION = '0.02';
4300f56a 9
10use base 'Class::MOP::Class';
11
12sub construct_instance {
13 my ($class, %params) = @_;
14 my $instance = {};
c9e77dbb 15 foreach my $attr ($class->compute_all_applicable_attributes()) {
4300f56a 16 # if the attr has an init_arg, use that, otherwise,
17 # use the attributes name itself as the init_arg
651955fb 18 my $init_arg = $attr->init_arg();
4300f56a 19 # try to fetch the init arg from the %params ...
20 my $val;
21 $val = $params{$init_arg} if exists $params{$init_arg};
22 # now add this to the instance structure
23 # only if we have found a value at all
24 $instance->{$attr->name} = $val if defined $val;
25 }
26 return $instance;
27}
28
046688ed 29package # hide the package from PAUSE
30 LazyClass::Attribute;
4300f56a 31
32use strict;
33use warnings;
34
b9dfbf78 35use Carp 'confess';
36
99e5b7e8 37our $VERSION = '0.02';
4300f56a 38
39use base 'Class::MOP::Attribute';
40
41sub generate_accessor_method {
42 my ($self, $attr_name) = @_;
43 sub {
44 if (scalar(@_) == 2) {
45 $_[0]->{$attr_name} = $_[1];
46 }
47 else {
48 if (!exists $_[0]->{$attr_name}) {
49 my $attr = $self->associated_class->get_attribute($attr_name);
50 $_[0]->{$attr_name} = $attr->has_default ? $attr->default($_[0]) : undef;
51 }
52 $_[0]->{$attr_name};
53 }
54 };
55}
56
57sub generate_reader_method {
58 my ($self, $attr_name) = @_;
59 sub {
b9dfbf78 60 confess "Cannot assign a value to a read-only accessor" if @_ > 1;
4300f56a 61 if (!exists $_[0]->{$attr_name}) {
62 my $attr = $self->associated_class->get_attribute($attr_name);
63 $_[0]->{$attr_name} = $attr->has_default ? $attr->default($_[0]) : undef;
64 }
65 $_[0]->{$attr_name};
66 };
67}
68
691;
70
71__END__
72
73=pod
74
75=head1 NAME
76
77LazyClass - An example metaclass with lazy initialization
78
79=head1 SYNOPSIS
80
81 package BinaryTree;
82
677eb158 83 use metaclass 'LazyClass' => (
84 ':attribute_metaclass' => 'LazyClass::Attribute'
85 );
4300f56a 86
87 BinaryTree->meta->add_attribute('$:node' => (
88 accessor => 'node',
89 init_arg => ':node'
90 ));
91
92 BinaryTree->meta->add_attribute('$:left' => (
93 reader => 'left',
94 default => sub { BinaryTree->new() }
95 ));
96
97 BinaryTree->meta->add_attribute('$:right' => (
98 reader => 'right',
99 default => sub { BinaryTree->new() }
100 ));
101
5659d76e 102 sub new {
4300f56a 103 my $class = shift;
5659d76e 104 $class->meta->new_object(@_);
4300f56a 105 }
106
107 # ... later in code
108
109 my $btree = BinaryTree->new();
110 # ... $btree is an empty hash, no keys are initialized yet
111
112=head1 DESCRIPTION
113
114This is an example metclass in which all attributes are created
115lazily. This means that no entries are made in the instance HASH
116until the last possible moment.
117
118The example above of a binary tree is a good use for such a
119metaclass because it allows the class to be space efficient
120without complicating the programing of it. This would also be
121ideal for a class which has a large amount of attributes,
122several of which are optional.
123
124=head1 AUTHOR
125
126Stevan Little E<lt>stevan@iinteractive.comE<gt>
127
128=head1 COPYRIGHT AND LICENSE
129
130Copyright 2006 by Infinity Interactive, Inc.
131
132L<http://www.iinteractive.com>
133
134This library is free software; you can redistribute it and/or modify
135it under the same terms as Perl itself.
136
137=cut