X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMouse.git;a=blobdiff_plain;f=lib%2FMouse%2FMeta%2FClass.pm;h=06c4f354ccbf437aa64556b1c1f0f6c1c7788bc3;hp=1093e0220f30b275a1cd8d79d2c181086fdc6878;hb=1b9e472d8c7e704eced9b2ea83194f83f0265018;hpb=121acb8a89acd75e7a664241df7e8220d864c879 diff --git a/lib/Mouse/Meta/Class.pm b/lib/Mouse/Meta/Class.pm index 1093e02..06c4f35 100644 --- a/lib/Mouse/Meta/Class.pm +++ b/lib/Mouse/Meta/Class.pm @@ -78,38 +78,50 @@ sub get_all_method_names { $self->linearized_isa; } -sub add_attribute { +sub _process_attribute{ my $self = shift; + my $name = shift; - if (@_ == 1 && blessed($_[0])) { - my $attr = shift @_; - $self->{'attributes'}{$attr->name} = $attr; - } - else { - my $names = shift @_; - $names = [$names] if !ref($names); - my $metaclass = 'Mouse::Meta::Attribute'; - my %options = (@_ == 1 ? %{$_[0]} : @_); - - if ( my $metaclass_name = delete $options{metaclass} ) { - my $new_class = Mouse::Util::resolve_metaclass_alias( - 'Attribute', - $metaclass_name - ); - if ( $metaclass ne $new_class ) { - $metaclass = $new_class; - } - } + my $args = (@_ == 1) ? $_[0] : { @_ }; - for my $name (@$names) { - if ($name =~ s/^\+//) { - $metaclass->clone_parent($self, $name, %options); - } - else { - $metaclass->create($self, $name, %options); - } + defined($name) + or $self->throw_error('You must provide a name for the attribute'); + + if ($name =~ s/^\+//) { + my $inherited_attr; + + foreach my $class($self->linearized_isa){ + my $meta = Mouse::Meta::Module::get_metaclass_by_name($class) or next; + $inherited_attr = $meta->get_attribute($name) and last; } + + defined($inherited_attr) + or $self->throw_error("Could not find an attribute by the name of '$name' to inherit from in ".$self->name); + + return $inherited_attr->clone_and_inherit_options($name, $args); + } + else{ + return Mouse::Meta::Attribute->interpolate_class_and_new($name, $args); + } +} + +sub add_attribute { + my $self = shift; + + my $attr = blessed($_[0]) ? $_[0] : $self->_process_attribute(@_); + + $attr->isa('Mouse::Meta::Attribute') + || $self->throw_error("Your attribute must be an instance of Mouse::Meta::Attribute (or a subclass)"); + + weaken( $attr->{associated_class} = $self ); + + $self->{attributes}{$attr->name} = $attr; + $attr->install_accessors(); + + if(!$attr->{associated_methods} && ($attr->{is} || '') ne 'bare'){ + Carp::cluck(qq{Attribute (}.$attr->name.qq{) of class }.$self->name.qq{ has no associated methods (did you mean to provide an "is" argument?)}); } + return $attr; } sub compute_all_applicable_attributes { shift->get_all_attributes(@_) } @@ -138,24 +150,32 @@ sub new_object { my $instance = bless {}, $self->name; + $self->_initialize_instance($instance, \%args); + return $instance; +} + +sub _initialize_instance{ + my($self, $instance, $args) = @_; + my @triggers_queue; foreach my $attribute ($self->get_all_attributes) { my $from = $attribute->init_arg; my $key = $attribute->name; - if (defined($from) && exists($args{$from})) { - $args{$from} = $attribute->coerce_constraint($args{$from}) + if (defined($from) && exists($args->{$from})) { + $args->{$from} = $attribute->coerce_constraint($args->{$from}) if $attribute->should_coerce; - $attribute->verify_against_type_constraint($args{$from}); - $instance->{$key} = $args{$from}; + $attribute->verify_against_type_constraint($args->{$from}); + + $instance->{$key} = $args->{$from}; weaken($instance->{$key}) if ref($instance->{$key}) && $attribute->is_weak_ref; if ($attribute->has_trigger) { - push @triggers_queue, [ $attribute->trigger, $args{$from} ]; + push @triggers_queue, [ $attribute->trigger, $args->{$from} ]; } } else {