-#!/usr/bin/env perl
package Mouse::Object;
use strict;
use warnings;
-use MRO::Compat;
-use Scalar::Util 'blessed';
-use Carp 'confess';
+use Mouse::Util;
sub new {
my $class = shift;
- my %args = @_;
- my $instance = bless {}, $class;
-
- for my $attribute ($class->meta->attributes) {
- my $key = $attribute->init_arg;
- my $default;
-
- if (!exists($args{$key})) {
- if (exists($attribute->{default}) || exists($attribute->{builder})) {
- unless ($attribute->{lazy}) {
- my $builder = $attribute->{builder};
- my $default = exists($attribute->{builder})
- ? $instance->$builder
- : ref($attribute->{default}) eq 'CODE'
- ? $attribute->{default}->()
- : $attribute->{default};
-
- $attribute->verify_type_constraint($default)
- if $attribute->has_type_constraint;
-
- $instance->{$key} = $default;
-
- Scalar::Util::weaken($instance->{$key})
- if $attribute->{weak_ref};
- }
- }
- else {
- if ($attribute->{required}) {
- confess "Attribute '$attribute->{name}' is required";
- }
- }
- }
-
- if (exists($args{$key})) {
- $attribute->verify_type_constraint($args{$key})
- if $attribute->has_type_constraint;
-
- $instance->{$key} = $args{$key};
-
- Scalar::Util::weaken($instance->{$key})
- if $attribute->{weak_ref};
-
- if ($attribute->{trigger}) {
- $attribute->{trigger}->($instance, $args{$key}, $attribute);
- }
- }
- }
- $instance->BUILDALL(\%args);
+ $class->throw_error('Cannot call new() on an instance') if ref $class;
+
+ my $args = $class->BUILDARGS(@_);
+ my $instance = Mouse::Meta::Class->initialize($class)->new_object($args);
+ $instance->BUILDALL($args);
return $instance;
}
+sub BUILDARGS {
+ my $class = shift;
+
+ if (scalar @_ == 1) {
+ (ref($_[0]) eq 'HASH')
+ || $class->meta->throw_error("Single parameters to new() must be a HASH ref");
+ return {%{$_[0]}};
+ }
+ else {
+ return {@_};
+ }
+}
+
sub DESTROY { shift->DEMOLISHALL }
sub BUILDALL {
# short circuit
return unless $self->can('BUILD');
- no strict 'refs';
-
- for my $class ($self->meta->linearized_isa) {
+ for my $class (reverse $self->meta->linearized_isa) {
+ no strict 'refs';
+ no warnings 'once';
my $code = *{ $class . '::BUILD' }{CODE}
or next;
$code->($self, @_);
}
+ return;
}
sub DEMOLISHALL {
# short circuit
return unless $self->can('DEMOLISH');
- no strict 'refs';
+ # We cannot count on being able to retrieve a previously made
+ # metaclass, _or_ being able to make a new one during global
+ # destruction. However, we should still be able to use mro at
+ # that time (at least tests suggest so ;)
- for my $class ($self->meta->linearized_isa) {
- my $code = *{ $class . '::DEMOLISH' }{CODE}
- or next;
- $code->($self, @_);
+ foreach my $class (@{ Mouse::Util::get_linear_isa(ref $self) }) {
+ my $demolish = do{ no strict 'refs'; *{"${class}::DEMOLISH"}{CODE} };
+ $self->$demolish()
+ if defined $demolish;
}
+ return;
}
+sub dump {
+ my($self, $maxdepth) = @_;
+
+ require 'Data/Dumper.pm'; # we don't want to create its namespace
+ my $dd = Data::Dumper->new([$self]);
+ $dd->Maxdepth(defined($maxdepth) ? $maxdepth : 1);
+ return $dd->Dump();
+}
+
+
+sub does {
+ my ($self, $role_name) = @_;
+ (defined $role_name)
+ || $self->meta->throw_error("You must supply a role name to does()");
+
+ return $self->meta->does_role($role_name);
+};
+
1;
__END__
You may put any business logic initialization in BUILD methods. You don't
need to redispatch or return any specific value.
+=head2 BUILDARGS
+
+Lets you override the arguments that C<new> takes. Return a hashref of
+parameters.
+
=head2 DEMOLISHALL
Calls L</DEMOLISH> on each class in the class hierarchy. This is called at
You may put any business logic deinitialization in DEMOLISH methods. You don't
need to redispatch or return any specific value.
+
+=head2 does $role_name
+
+This will check if the invocant's class "does" a given C<$role_name>.
+This is similar to "isa" for object, but it checks the roles instead.
+
+
+=head2 B<dump ($maxdepth)>
+
+From the Moose POD:
+
+ C'mon, how many times have you written the following code while debugging:
+
+ use Data::Dumper;
+ warn Dumper $obj;
+
+ It can get seriously annoying, so why not just use this.
+
+The implementation was lifted directly from Moose::Object.
+
=cut
+