use Scalar::Util 'weaken', 'reftype', 'blessed';
use Try::Tiny;
+use Class::MOP::Mixin::AttributeBase;
use Class::MOP::Mixin::HasAttributes;
use Class::MOP::Mixin::HasMethods;
use Class::MOP::Class;
# _construct_class_instance method.
## --------------------------------------------------------
-## Class::MOP::Attribute
-
-Class::MOP::Attribute->meta->add_attribute(
+## Class::MOP::Mixin::AttributeBase
+Class::MOP::Mixin::AttributeBase->meta->add_attribute(
Class::MOP::Attribute->new('name' => (
reader => {
# NOTE: we need to do this in order
#
# we just alias the original method
# rather than re-produce it here
- 'name' => \&Class::MOP::Attribute::name
+ 'name' => \&Class::MOP::Mixin::AttributeBase::name
}
))
);
-Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('associated_class' => (
- reader => {
- # NOTE: we need to do this in order
- # for the instance meta-object to
- # not fall into meta-circular death
- #
- # we just alias the original method
- # rather than re-produce it here
- 'associated_class' => \&Class::MOP::Attribute::associated_class
- }
- ))
-);
-
-Class::MOP::Attribute->meta->add_attribute(
+Class::MOP::Mixin::AttributeBase->meta->add_attribute(
Class::MOP::Attribute->new('accessor' => (
- reader => { 'accessor' => \&Class::MOP::Attribute::accessor },
- predicate => { 'has_accessor' => \&Class::MOP::Attribute::has_accessor },
+ reader => { 'accessor' => \&Class::MOP::Mixin::AttributeBase::accessor },
+ predicate => { 'has_accessor' => \&Class::MOP::Mixin::AttributeBase::has_accessor },
))
);
-Class::MOP::Attribute->meta->add_attribute(
+Class::MOP::Mixin::AttributeBase->meta->add_attribute(
Class::MOP::Attribute->new('reader' => (
- reader => { 'reader' => \&Class::MOP::Attribute::reader },
- predicate => { 'has_reader' => \&Class::MOP::Attribute::has_reader },
+ reader => { 'reader' => \&Class::MOP::Mixin::AttributeBase::reader },
+ predicate => { 'has_reader' => \&Class::MOP::Mixin::AttributeBase::has_reader },
))
);
-Class::MOP::Attribute->meta->add_attribute(
+Class::MOP::Mixin::AttributeBase->meta->add_attribute(
Class::MOP::Attribute->new('initializer' => (
- reader => { 'initializer' => \&Class::MOP::Attribute::initializer },
- predicate => { 'has_initializer' => \&Class::MOP::Attribute::has_initializer },
+ reader => { 'initializer' => \&Class::MOP::Mixin::AttributeBase::initializer },
+ predicate => { 'has_initializer' => \&Class::MOP::Mixin::AttributeBase::has_initializer },
))
);
-Class::MOP::Attribute->meta->add_attribute(
+Class::MOP::Mixin::AttributeBase->meta->add_attribute(
Class::MOP::Attribute->new('definition_context' => (
- reader => { 'definition_context' => \&Class::MOP::Attribute::definition_context },
+ reader => { 'definition_context' => \&Class::MOP::Mixin::AttributeBase::definition_context },
))
);
-Class::MOP::Attribute->meta->add_attribute(
+Class::MOP::Mixin::AttributeBase->meta->add_attribute(
Class::MOP::Attribute->new('writer' => (
- reader => { 'writer' => \&Class::MOP::Attribute::writer },
- predicate => { 'has_writer' => \&Class::MOP::Attribute::has_writer },
+ reader => { 'writer' => \&Class::MOP::Mixin::AttributeBase::writer },
+ predicate => { 'has_writer' => \&Class::MOP::Mixin::AttributeBase::has_writer },
))
);
-Class::MOP::Attribute->meta->add_attribute(
+Class::MOP::Mixin::AttributeBase->meta->add_attribute(
Class::MOP::Attribute->new('predicate' => (
- reader => { 'predicate' => \&Class::MOP::Attribute::predicate },
- predicate => { 'has_predicate' => \&Class::MOP::Attribute::has_predicate },
+ reader => { 'predicate' => \&Class::MOP::Mixin::AttributeBase::predicate },
+ predicate => { 'has_predicate' => \&Class::MOP::Mixin::AttributeBase::has_predicate },
))
);
-Class::MOP::Attribute->meta->add_attribute(
+Class::MOP::Mixin::AttributeBase->meta->add_attribute(
Class::MOP::Attribute->new('clearer' => (
- reader => { 'clearer' => \&Class::MOP::Attribute::clearer },
- predicate => { 'has_clearer' => \&Class::MOP::Attribute::has_clearer },
+ reader => { 'clearer' => \&Class::MOP::Mixin::AttributeBase::clearer },
+ predicate => { 'has_clearer' => \&Class::MOP::Mixin::AttributeBase::has_clearer },
))
);
-Class::MOP::Attribute->meta->add_attribute(
+Class::MOP::Mixin::AttributeBase->meta->add_attribute(
Class::MOP::Attribute->new('builder' => (
- reader => { 'builder' => \&Class::MOP::Attribute::builder },
- predicate => { 'has_builder' => \&Class::MOP::Attribute::has_builder },
+ reader => { 'builder' => \&Class::MOP::Mixin::AttributeBase::builder },
+ predicate => { 'has_builder' => \&Class::MOP::Mixin::AttributeBase::has_builder },
))
);
-Class::MOP::Attribute->meta->add_attribute(
+Class::MOP::Mixin::AttributeBase->meta->add_attribute(
Class::MOP::Attribute->new('init_arg' => (
- reader => { 'init_arg' => \&Class::MOP::Attribute::init_arg },
- predicate => { 'has_init_arg' => \&Class::MOP::Attribute::has_init_arg },
+ reader => { 'init_arg' => \&Class::MOP::Mixin::AttributeBase::init_arg },
+ predicate => { 'has_init_arg' => \&Class::MOP::Mixin::AttributeBase::has_init_arg },
))
);
-Class::MOP::Attribute->meta->add_attribute(
+Class::MOP::Mixin::AttributeBase->meta->add_attribute(
Class::MOP::Attribute->new('default' => (
# default has a custom 'reader' method ...
- predicate => { 'has_default' => \&Class::MOP::Attribute::has_default },
+ predicate => { 'has_default' => \&Class::MOP::Mixin::AttributeBase::has_default },
))
);
+Class::MOP::Mixin::AttributeBase->meta->add_attribute(
+ Class::MOP::Attribute->new('insertion_order' => (
+ reader => { 'insertion_order' => \&Class::MOP::Mixin::AttributeBase::insertion_order },
+ writer => { '_set_insertion_order' => \&Class::MOP::Mixin::AttributeBase::_set_insertion_order },
+ predicate => { 'has_insertion_order' => \&Class::MOP::Mixin::AttributeBase::has_insertion_order },
+ ))
+);
+
+## --------------------------------------------------------
+## Class::MOP::Attribute
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('associated_methods' => (
- reader => { 'associated_methods' => \&Class::MOP::Attribute::associated_methods },
- default => sub { [] }
+ Class::MOP::Attribute->new('associated_class' => (
+ reader => {
+ # NOTE: we need to do this in order
+ # for the instance meta-object to
+ # not fall into meta-circular death
+ #
+ # we just alias the original method
+ # rather than re-produce it here
+ 'associated_class' => \&Class::MOP::Attribute::associated_class
+ }
))
);
Class::MOP::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('insertion_order' => (
- reader => { 'insertion_order' => \&Class::MOP::Attribute::insertion_order },
- writer => { '_set_insertion_order' => \&Class::MOP::Attribute::_set_insertion_order },
- predicate => { 'has_insertion_order' => \&Class::MOP::Attribute::has_insertion_order },
+ Class::MOP::Attribute->new('associated_methods' => (
+ reader => { 'associated_methods' => \&Class::MOP::Attribute::associated_methods },
+ default => sub { [] }
))
);
constructor_name => undef,
inline_accessors => 0,
) for qw/
+ Class::MOP::Mixin::AttributeBase
Class::MOP::Mixin::HasAttributes
Class::MOP::Mixin::HasMethods
/;
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
-use base 'Class::MOP::Object';
+use base 'Class::MOP::Object', 'Class::MOP::Mixin::AttributeBase';
# NOTE: (meta-circularity)
# This method will be replaced in the
confess("Setting both default and builder is not allowed.")
if exists $options{default};
} else {
- (is_default_a_coderef(\%options))
+ ($class->is_default_a_coderef(\%options))
|| confess("References are not allowed as default values, you must ".
"wrap the default of '$name' in a CODE reference (ex: sub { [] } and not [])")
if exists $options{default} && ref $options{default};
$instance->$initializer($value, $callback, $self);
}
-# NOTE:
-# the next bunch of methods will get bootstrapped
-# away in the Class::MOP bootstrapping section
-
sub associated_class { $_[0]->{'associated_class'} }
sub associated_methods { $_[0]->{'associated_methods'} }
-sub has_accessor { defined($_[0]->{'accessor'}) }
-sub has_reader { defined($_[0]->{'reader'}) }
-sub has_writer { defined($_[0]->{'writer'}) }
-sub has_predicate { defined($_[0]->{'predicate'}) }
-sub has_clearer { defined($_[0]->{'clearer'}) }
-sub has_builder { defined($_[0]->{'builder'}) }
-sub has_init_arg { defined($_[0]->{'init_arg'}) }
-sub has_default { defined($_[0]->{'default'}) }
-sub has_initializer { defined($_[0]->{'initializer'}) }
-sub has_insertion_order { defined($_[0]->{'insertion_order'}) }
-
-sub accessor { $_[0]->{'accessor'} }
-sub reader { $_[0]->{'reader'} }
-sub writer { $_[0]->{'writer'} }
-sub predicate { $_[0]->{'predicate'} }
-sub clearer { $_[0]->{'clearer'} }
-sub builder { $_[0]->{'builder'} }
-sub init_arg { $_[0]->{'init_arg'} }
-sub initializer { $_[0]->{'initializer'} }
-sub definition_context { $_[0]->{'definition_context'} }
-sub insertion_order { $_[0]->{'insertion_order'} }
-sub _set_insertion_order { $_[0]->{'insertion_order'} = $_[1] }
-
-# end bootstrapped away method section.
-# (all methods below here are kept intact)
-
-sub has_read_method { $_[0]->has_reader || $_[0]->has_accessor }
-sub has_write_method { $_[0]->has_writer || $_[0]->has_accessor }
-
sub get_read_method {
my $self = shift;
my $reader = $self->reader || $self->accessor;
}
}
-sub is_default_a_coderef {
- my ($value) = $_[0]->{'default'};
- return unless ref($value);
- return ref($value) eq 'CODE' || (blessed($value) && $value->isa('Class::MOP::Method'));
-}
-
-sub default {
- my ($self, $instance) = @_;
- if (defined $instance && $self->is_default_a_coderef) {
- # if the default is a CODE ref, then
- # we pass in the instance and default
- # can return a value based on that
- # instance. Somewhat crude, but works.
- return $self->{'default'}->($instance);
- }
- $self->{'default'};
-}
-
# slots
sub slots { (shift)->name }
--- /dev/null
+package Class::MOP::Mixin::AttributeBase;
+
+use strict;
+use warnings;
+
+use Scalar::Util 'blessed';
+
+our $VERSION = '0.97';
+$VERSION = eval $VERSION;
+our $AUTHORITY = 'cpan:STEVAN';
+
+use base 'Class::MOP::Object';
+
+sub has_accessor { defined $_[0]->{'accessor'} }
+sub has_reader { defined $_[0]->{'reader'} }
+sub has_writer { defined $_[0]->{'writer'} }
+sub has_predicate { defined $_[0]->{'predicate'} }
+sub has_clearer { defined $_[0]->{'clearer'} }
+sub has_builder { defined $_[0]->{'builder'} }
+sub has_init_arg { defined $_[0]->{'init_arg'} }
+sub has_default { defined $_[0]->{'default'} }
+sub has_initializer { defined $_[0]->{'initializer'} }
+sub has_insertion_order { defined $_[0]->{'insertion_order'} }
+
+sub accessor { $_[0]->{'accessor'} }
+sub reader { $_[0]->{'reader'} }
+sub writer { $_[0]->{'writer'} }
+sub predicate { $_[0]->{'predicate'} }
+sub clearer { $_[0]->{'clearer'} }
+sub builder { $_[0]->{'builder'} }
+sub init_arg { $_[0]->{'init_arg'} }
+sub initializer { $_[0]->{'initializer'} }
+sub definition_context { $_[0]->{'definition_context'} }
+sub insertion_order { $_[0]->{'insertion_order'} }
+sub _set_insertion_order { $_[0]->{'insertion_order'} = $_[1] }
+
+sub has_read_method { $_[0]->has_reader || $_[0]->has_accessor }
+sub has_write_method { $_[0]->has_writer || $_[0]->has_accessor }
+
+sub is_default_a_coderef {
+ # Uber hack because it is called from CMOP::Attribute constructor as
+ # $class->is_default_a_coderef(\%options)
+ my ($value) = ref $_[0] ? $_[0]->{'default'} : $_[1]->{'default'};
+
+ return unless ref($value);
+
+ return ref($value) eq 'CODE'
+ || ( blessed($value) && $value->isa('Class::MOP::Method') );
+}
+
+sub default {
+ my ( $self, $instance ) = @_;
+ if ( defined $instance && $self->is_default_a_coderef ) {
+ # if the default is a CODE ref, then we pass in the instance and
+ # default can return a value based on that instance. Somewhat crude,
+ # but works.
+ return $self->{'default'}->($instance);
+ }
+ $self->{'default'};
+}
+
+1;
BEGIN {
use_ok('Class::MOP');
+ use_ok('Class::MOP::Mixin::AttributeBase');
use_ok('Class::MOP::Mixin::HasAttributes');
use_ok('Class::MOP::Mixin::HasMethods');
use_ok('Class::MOP::Package');
'Class::MOP::Method::Accessor' => Class::MOP::Method::Accessor->meta,
'Class::MOP::Method::Constructor' =>
Class::MOP::Method::Constructor->meta,
+ 'Class::MOP::Mixin::AttributeBase' => Class::MOP::Mixin::AttributeBase->meta,
'Class::MOP::Mixin::HasAttributes' => Class::MOP::Mixin::HasAttributes->meta,
'Class::MOP::Mixin::HasMethods' => Class::MOP::Mixin::HasMethods->meta,
'Class::MOP::Package' => Class::MOP::Package->meta,
Class::MOP::Method::Generated->meta,
Class::MOP::Method::Inlined->meta,
Class::MOP::Method::Wrapped->meta,
+ Class::MOP::Mixin::AttributeBase->meta,
Class::MOP::Mixin::HasAttributes->meta,
Class::MOP::Mixin::HasMethods->meta,
Class::MOP::Module->meta,
Class::MOP::Class
Class::MOP::Class::Immutable::Class::MOP::Class
Class::MOP::Class::Immutable::Trait
+ Class::MOP::Mixin::AttributeBase
Class::MOP::Mixin::HasAttributes
Class::MOP::Mixin::HasMethods
Class::MOP::Instance
{
my $attr = Class::MOP::Attribute->new('$test');
- is($attr->meta, Class::MOP::Attribute->meta, '... instance and class both lead to the same meta');
+ is( $attr->meta, Class::MOP::Attribute->meta,
+ '... instance and class both lead to the same meta' );
}
{
my $meta = Class::MOP::Attribute->meta();
- isa_ok($meta, 'Class::MOP::Class');
+ isa_ok( $meta, 'Class::MOP::Class' );
my @methods = qw(
new
remove_accessors
_new
- );
+ );
is_deeply(
- [ sort $meta->get_method_list ],
+ [
+ sort Class::MOP::Mixin::AttributeBase->meta->get_method_list,
+ $meta->get_method_list
+ ],
[ sort @methods ],
- '... our method list matches');
+ '... our method list matches'
+ );
foreach my $method_name (@methods) {
- ok($meta->has_method($method_name), '... Class::MOP::Attribute->has_method(' . $method_name . ')');
+ ok( $meta->find_method_by_name($method_name),
+ '... Class::MOP::Attribute->find_method_by_name(' . $method_name . ')' );
}
my @attributes = (
);
is_deeply(
- [ sort $meta->get_attribute_list ],
+ [
+ sort Class::MOP::Mixin::AttributeBase->meta->get_attribute_list,
+ $meta->get_attribute_list
+ ],
[ sort @attributes ],
- '... our attribute list matches');
+ '... our attribute list matches'
+ );
foreach my $attribute_name (@attributes) {
- ok($meta->has_attribute($attribute_name), '... Class::MOP::Attribute->has_attribute(' . $attribute_name . ')');
+ ok( $meta->find_attribute_by_name($attribute_name),
+ '... Class::MOP::Attribute->find_attribute_by_name('
+ . $attribute_name
+ . ')' );
}
# We could add some tests here to make sure that
+++ /dev/null
-#include "mop.h"
-
-MODULE = Class::MOP::Attribute PACKAGE = Class::MOP::Attribute
-
-PROTOTYPES: DISABLE
-
-BOOT:
- INSTALL_SIMPLE_READER(Attribute, name);
--- /dev/null
+#include "mop.h"
+
+MODULE = Class::MOP::Mixin::AttributeBase PACKAGE = Class::MOP::Mixin::AttributeBase
+
+PROTOTYPES: DISABLE
+
+BOOT:
+ INSTALL_SIMPLE_READER(Mixin::AttributeBase, name);
EXTERN_C XS(boot_Class__MOP__Mixin__HasMethods);
EXTERN_C XS(boot_Class__MOP__Package);
-EXTERN_C XS(boot_Class__MOP__Attribute);
+EXTERN_C XS(boot_Class__MOP__Mixin__AttributeBase);
EXTERN_C XS(boot_Class__MOP__Method);
MODULE = Class::MOP PACKAGE = Class::MOP
MOP_CALL_BOOT (boot_Class__MOP__Mixin__HasMethods);
MOP_CALL_BOOT (boot_Class__MOP__Package);
- MOP_CALL_BOOT (boot_Class__MOP__Attribute);
+ MOP_CALL_BOOT (boot_Class__MOP__Mixin__AttributeBase);
MOP_CALL_BOOT (boot_Class__MOP__Method);
# use prototype here to be compatible with get_code_info from Sub::Identify