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=51a496f125a3bf5777e960819cda5916c173921c;hp=c1e614a544b38c88c3aa205e77012e587aea3fa6;hb=f18ecf2a2722afd64a24f543fe503ae9dc969e86;hpb=8e64d0fa5da64639074f77d3da9b2f7aa20cce93 diff --git a/lib/Mouse/Meta/Class.pm b/lib/Mouse/Meta/Class.pm index c1e614a..51a496f 100644 --- a/lib/Mouse/Meta/Class.pm +++ b/lib/Mouse/Meta/Class.pm @@ -81,35 +81,55 @@ sub get_all_method_names { sub add_attribute { my $self = shift; - if (@_ == 1 && blessed($_[0])) { - my $attr = shift @_; - $self->{'attributes'}{$attr->name} = $attr; + my($attr, $name); + + if(blessed $_[0]){ + $attr = $_[0]; + + $attr->isa('Mouse::Meta::Attribute') + || $self->throw_error("Your attribute must be an instance of Mouse::Meta::Attribute (or a subclass)"); + + $name = $attr->name; } - 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; + else{ + # _process_attribute + $name = shift; + + my %args = (@_ == 1) ? %{$_[0]} : @_; + + defined($name) + or $self->throw_error('You must provide a name for the attribute'); + + if ($name =~ s/^\+//) { # inherited attributes + 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); + + $attr = $inherited_attr->clone_and_inherit_options($name, \%args); } + else{ + my($attribute_class, @traits) = Mouse::Meta::Attribute->interpolate_class($name, \%args); + $args{traits} = \@traits if @traits; - for my $name (@$names) { - if ($name =~ s/^\+//) { - $metaclass->clone_parent($self, $name, %options); - } - else { - $metaclass->create($self, $name, %options); - } + $attr = $attribute_class->new($name, \%args); } } + + 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 +158,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 { @@ -192,25 +220,21 @@ sub new_object { $trigger->($instance, $value); } + if($self->is_anon_class){ + $instance->{__METACLASS__} = $self; + } + return $instance; } sub clone_object { my $class = shift; my $instance = shift; + my %params = (@_ == 1) ? %{$_[0]} : @_; (blessed($instance) && $instance->isa($class->name)) || $class->throw_error("You must pass an instance of the metaclass (" . $class->name . "), not ($instance)"); - $class->clone_instance($instance, @_); -} - -sub clone_instance { - my ($class, $instance, %params) = @_; - - (blessed($instance)) - || $class->throw_error("You can only clone instances, ($instance) is not a blessed instance"); - my $clone = bless { %$instance }, ref $instance; foreach my $attr ($class->get_all_attributes()) { @@ -222,7 +246,13 @@ sub clone_instance { } return $clone; +} + +sub clone_instance { + my ($class, $instance, %params) = @_; + Carp::cluck('clone_instance has been deprecated. Use clone_object instead'); + return $class->clone_object($instance, %params); } sub make_immutable { @@ -339,7 +369,7 @@ __END__ =head1 NAME -Mouse::Meta::Class - hook into the Mouse MOP +Mouse::Meta::Class - The Mouse class metaclass =head1 METHODS @@ -348,10 +378,6 @@ Mouse::Meta::Class - hook into the Mouse MOP Finds or creates a Mouse::Meta::Class instance for the given ClassName. Only one instance should exist for a given class. -=head2 new %args -> Mouse::Meta::Class - -Creates a new Mouse::Meta::Class. Don't call this directly. - =head2 name -> ClassName Returns the name of the owner class. @@ -360,7 +386,7 @@ Returns the name of the owner class. Gets (or sets) the list of superclasses of the owner class. -=head2 add_attribute (Mouse::Meta::Attribute| name => spec) +=head2 add_attribute (name => spec | Mouse::Meta::Attribute) Begins keeping track of the existing L for the owner class. @@ -393,15 +419,18 @@ Returns the L with the given name. Returns the list of classes in method dispatch order, with duplicates removed. +=head2 new_object Parameters -> Instance + +Create a new instance. + =head2 clone_object Instance -> Instance Clones the given C which must be an instance governed by this metaclass. -=head2 clone_instance Instance, Parameters -> Instance +=head1 SEE ALSO -The clone_instance method has been made private. -The public version is deprecated. +L =cut