ROLES
[gitmo/Moose.git] / lib / Moose / Meta / Class.pm
1
2 package Moose::Meta::Class;
3
4 use strict;
5 use warnings;
6
7 use Carp         'confess';
8 use Scalar::Util 'weaken', 'blessed';
9
10 our $VERSION = '0.04';
11
12 use base 'Class::MOP::Class';
13
14 sub construct_instance {
15     my ($class, %params) = @_;
16     my $instance = $params{'__INSTANCE__'} || {};
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;        
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         }
31         # if nothing was in the %params, we can use the 
32         # attribute's default value (if it has one)
33         if (!defined $val && $attr->has_default) {
34             $val = $attr->default($instance); 
35         }
36                 if (defined $val) {
37                     if ($attr->has_type_constraint) {
38                     if ($attr->should_coerce && $attr->type_constraint->has_coercion) {
39                         $val = $attr->type_constraint->coercion->coerce($val);
40                     }   
41                 (defined($attr->type_constraint->check($val))) 
42                     || confess "Attribute (" . $attr->name . ") does not pass the type contraint with '$val'";                  
43             }
44                 }
45         $instance->{$attr->name} = $val;
46         if (defined $val && $attr->is_weak_ref) {
47             weaken($instance->{$attr->name});
48         }
49     }
50     return $instance;
51 }
52
53 sub 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
69 sub 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";    
76     $self->add_method($name => sub {
77         my @args = @_;
78         no strict   'refs';
79         no warnings 'redefine';
80         local *{$_super_package . '::super'} = sub { $super->(@args) };
81         return $method->(@args);
82     });
83 }
84
85 sub add_augment_method_modifier {
86     my ($self, $name, $method) = @_;    
87     my $super = $self->find_next_method_by_name($name);
88     (defined $super)
89         || confess "You cannot augment '$name' because it has no super method";
90     $self->add_method($name => sub {
91         my @args = @_;
92         no strict   'refs';
93         no warnings 'redefine';
94         local *{$super->package_name . '::inner'} = sub { $method->(@args) };
95         return $super->(@args);
96     });    
97 }
98
99 1;
100
101 __END__
102
103 =pod
104
105 =head1 NAME
106
107 Moose::Meta::Class - The Moose metaclass
108
109 =head1 DESCRIPTION
110
111 This is a subclass of L<Class::MOP::Class> with Moose specific 
112 extensions.
113
114 For the most part, the only time you will ever encounter an 
115 instance of this class is if you are doing some serious deep 
116 introspection. To really understand this class, you need to refer 
117 to the L<Class::MOP::Class> documentation.
118
119 =head1 METHODS
120
121 =over 4
122
123 =item B<construct_instance>
124
125 This provides some Moose specific extensions to this method, you 
126 almost never call this method directly unless you really know what 
127 you are doing. 
128
129 This method makes sure to handle the moose weak-ref, type-constraint
130 and type coercion features. 
131
132 =item B<add_override_method_modifier ($name, $method)>
133
134 =item B<add_augment_method_modifier ($name, $method)>
135
136 =back
137
138 =head1 BUGS
139
140 All complex software has bugs lurking in it, and this module is no 
141 exception. If you find a bug please either email me, or add the bug
142 to cpan-RT.
143
144 =head1 AUTHOR
145
146 Stevan Little E<lt>stevan@iinteractive.comE<gt>
147
148 =head1 COPYRIGHT AND LICENSE
149
150 Copyright 2006 by Infinity Interactive, Inc.
151
152 L<http://www.iinteractive.com>
153
154 This library is free software; you can redistribute it and/or modify
155 it under the same terms as Perl itself. 
156
157 =cut