Verify type constraints in the constructor
[gitmo/Mouse.git] / lib / Mouse / Object.pm
CommitLineData
c3398f5b 1#!/usr/bin/env perl
2package Mouse::Object;
3use strict;
4use warnings;
5use MRO::Compat;
6
7use Scalar::Util 'blessed';
8use Carp 'confess';
9
10sub new {
11 my $class = shift;
12 my %args = @_;
13 my $instance = bless {}, $class;
14
15 for my $attribute ($class->meta->attributes) {
16 my $key = $attribute->init_arg;
17 my $default;
18
19 if (!exists($args{$key})) {
20 if (exists($attribute->{default})) {
21 unless ($attribute->{lazy}) {
5aa30ced 22 my $default = ref($attribute->{default}) eq 'CODE'
23 ? $attribute->{default}->()
24 : $attribute->{default};
25
26 $attribute->verify_type_constraint($default)
27 if $attribute->has_type_constraint;
28
29 $instance->{$key} = $default;
30
31 Scalar::Util::weaken($instance->{$key})
32 if $attribute->{weak_ref};
c3398f5b 33 }
34 }
35 else {
36 if ($attribute->{required}) {
37 confess "Attribute '$attribute->{name}' is required";
38 }
39 }
40 }
41
42 if (exists($args{$key})) {
5aa30ced 43 $attribute->verify_type_constraint($args{$key})
44 if $attribute->has_type_constraint;
45
c3398f5b 46 $instance->{$key} = $args{$key};
5aa30ced 47
c3398f5b 48 Scalar::Util::weaken($instance->{$key})
49 if $attribute->{weak_ref};
50
51 if ($attribute->{trigger}) {
52 $attribute->{trigger}->($instance, $args{$key}, $attribute);
53 }
54 }
55 }
56
57 $instance->BUILDALL(\%args);
58
59 return $instance;
60}
61
62sub DESTROY { shift->DEMOLISHALL }
63
64sub BUILDALL {
65 my $self = shift;
66
67 # short circuit
68 return unless $self->can('BUILD');
69
70 no strict 'refs';
71
72 for my $class ($self->meta->linearized_isa) {
73 my $code = *{ $class . '::BUILD' }{CODE}
74 or next;
75 $code->($self, @_);
76 }
77}
78
79sub DEMOLISHALL {
80 my $self = shift;
81
82 # short circuit
83 return unless $self->can('DEMOLISH');
84
85 no strict 'refs';
86
87 for my $class ($self->meta->linearized_isa) {
88 my $code = *{ $class . '::DEMOLISH' }{CODE}
89 or next;
90 $code->($self, @_);
91 }
92}
93
941;
95
96__END__
97
98=head1 NAME
99
100Mouse::Object - we don't need to steenkin' constructor
101
102=head1 METHODS
103
104=head2 new arguments -> object
105
106Instantiates a new Mouse::Object. This is obviously intended for subclasses.
107
108=head2 BUILDALL \%args
109
110Calls L</BUILD> on each class in the class hierarchy. This is called at the
111end of L</new>.
112
113=head2 BUILD \%args
114
115You may put any business logic initialization in BUILD methods. You don't
116need to redispatch or return any specific value.
117
118=head2 DEMOLISHALL
119
120Calls L</DEMOLISH> on each class in the class hierarchy. This is called at
121L</DESTROY> time.
122
123=head2 DEMOLISH
124
125You may put any business logic deinitialization in DEMOLISH methods. You don't
126need to redispatch or return any specific value.
127
128=cut
129