updatin
[gitmo/Moose.git] / lib / Moose / Meta / Class.pm
CommitLineData
c0e30cf5 1
2package Moose::Meta::Class;
3
4use strict;
5use warnings;
6
6ba6d68c 7use Carp 'confess';
a7d0cd00 8use Scalar::Util 'weaken', 'blessed';
a15dff8d 9
78cd1d3b 10our $VERSION = '0.04';
bc1e29b5 11
c0e30cf5 12use base 'Class::MOP::Class';
13
a15dff8d 14sub construct_instance {
15 my ($class, %params) = @_;
e522431d 16 my $instance = $params{'__INSTANCE__'} || {};
a15dff8d 17 foreach my $attr ($class->compute_all_applicable_attributes()) {
18 my $init_arg = $attr->init_arg();
19 # try to fetch the init arg from the %params ...
20 my $val;
ca01a97b 21 if (exists $params{$init_arg}) {
22 $val = $params{$init_arg};
23 }
24 else {
25 # skip it if it's lazy
26 next if $attr->is_lazy;
27 # and die if it is required
28 confess "Attribute (" . $attr->name . ") is required"
29 if $attr->is_required
30 }
a15dff8d 31 # if nothing was in the %params, we can use the
32 # attribute's default value (if it has one)
8339fae2 33 if (!defined $val && $attr->has_default) {
34 $val = $attr->default($instance);
35 }
00867c44 36 if (defined $val) {
00867c44 37 if ($attr->has_type_constraint) {
34a66aa3 38 if ($attr->should_coerce && $attr->type_constraint->has_coercion) {
a27aa600 39 $val = $attr->type_constraint->coercion->coerce($val);
7415b2cb 40 }
a27aa600 41 (defined($attr->type_constraint->check($val)))
66811d63 42 || confess "Attribute (" . $attr->name . ") does not pass the type contraint with '$val'";
00867c44 43 }
a15dff8d 44 }
45 $instance->{$attr->name} = $val;
6ba6d68c 46 if (defined $val && $attr->is_weak_ref) {
47 weaken($instance->{$attr->name});
48 }
a15dff8d 49 }
50 return $instance;
51}
52
a7d0cd00 53sub has_method {
54 my ($self, $method_name) = @_;
55 (defined $method_name && $method_name)
56 || confess "You must define a method name";
57
58 my $sub_name = ($self->name . '::' . $method_name);
59
60 no strict 'refs';
61 return 0 if !defined(&{$sub_name});
62 my $method = \&{$sub_name};
63
64 return 1 if blessed($method) && $method->isa('Moose::Meta::Role::Method');
65 return $self->SUPER::has_method($method_name);
66}
67
68
78cd1d3b 69sub add_override_method_modifier {
70 my ($self, $name, $method, $_super_package) = @_;
71 # need this for roles ...
72 $_super_package ||= $self->name;
73 my $super = $self->find_next_method_by_name($name);
74 (defined $super)
75 || confess "You cannot override '$name' because it has no super method";
05d9eaf6 76 $self->add_method($name => bless sub {
78cd1d3b 77 my @args = @_;
78 no strict 'refs';
79 no warnings 'redefine';
80 local *{$_super_package . '::super'} = sub { $super->(@args) };
81 return $method->(@args);
05d9eaf6 82 } => 'Moose::Meta::Method::Overriden');
78cd1d3b 83}
84
85sub add_augment_method_modifier {
05d9eaf6 86 my ($self, $name, $method) = @_;
78cd1d3b 87 my $super = $self->find_next_method_by_name($name);
88 (defined $super)
05d9eaf6 89 || confess "You cannot augment '$name' because it has no super method";
90 my $_super_package = $super->package_name;
91 # BUT!,... if this is an overriden method ....
92 if ($super->isa('Moose::Meta::Method::Overriden')) {
93 # we need to be sure that we actually
94 # find the next method, which is not
95 # an 'override' method, the reason is
96 # that an 'override' method will not
97 # be the one calling inner()
98 my $real_super = $self->_find_next_method_by_name_which_is_not_overridden($name);
99 $_super_package = $real_super->package_name;
100 }
78cd1d3b 101 $self->add_method($name => sub {
102 my @args = @_;
103 no strict 'refs';
104 no warnings 'redefine';
05d9eaf6 105 local *{$_super_package . '::inner'} = sub { $method->(@args) };
78cd1d3b 106 return $super->(@args);
107 });
108}
109
05d9eaf6 110sub _find_next_method_by_name_which_is_not_overridden {
111 my ($self, $name) = @_;
112 my @methods = $self->find_all_methods_by_name($name);
113 foreach my $method (@methods) {
114 return $method->{code}
115 if blessed($method->{code}) && !$method->{code}->isa('Moose::Meta::Method::Overriden');
116 }
117 return undef;
118}
119
120package Moose::Meta::Method::Overriden;
121
122use strict;
123use warnings;
124
125our $VERSION = '0.01';
126
127use base 'Class::MOP::Method';
128
c0e30cf5 1291;
130
131__END__
132
133=pod
134
135=head1 NAME
136
e522431d 137Moose::Meta::Class - The Moose metaclass
c0e30cf5 138
c0e30cf5 139=head1 DESCRIPTION
140
e522431d 141This is a subclass of L<Class::MOP::Class> with Moose specific
142extensions.
143
6ba6d68c 144For the most part, the only time you will ever encounter an
145instance of this class is if you are doing some serious deep
146introspection. To really understand this class, you need to refer
147to the L<Class::MOP::Class> documentation.
148
c0e30cf5 149=head1 METHODS
150
151=over 4
152
a15dff8d 153=item B<construct_instance>
154
6ba6d68c 155This provides some Moose specific extensions to this method, you
156almost never call this method directly unless you really know what
157you are doing.
158
159This method makes sure to handle the moose weak-ref, type-constraint
160and type coercion features.
ef1d5f4b 161
e9ec68d6 162=item B<has_method ($name)>
163
164This accomidates Moose::Meta::Role::Method instances, which are
165aliased, instead of added, but still need to be counted as valid
166methods.
167
78cd1d3b 168=item B<add_override_method_modifier ($name, $method)>
169
170=item B<add_augment_method_modifier ($name, $method)>
171
c0e30cf5 172=back
173
174=head1 BUGS
175
176All complex software has bugs lurking in it, and this module is no
177exception. If you find a bug please either email me, or add the bug
178to cpan-RT.
179
c0e30cf5 180=head1 AUTHOR
181
182Stevan Little E<lt>stevan@iinteractive.comE<gt>
183
184=head1 COPYRIGHT AND LICENSE
185
186Copyright 2006 by Infinity Interactive, Inc.
187
188L<http://www.iinteractive.com>
189
190This library is free software; you can redistribute it and/or modify
191it under the same terms as Perl itself.
192
193=cut