Revision history for Perl extension Class-MOP.
+0.05
+ * Class::MOP::Class
+ - added the &attribute_metaclass and &method_metaclass
+ functions which return a metaclass name to use for
+ attributes/methods respectively
+
+ * examples/
+ - adjusted the example code and tests to use the new
+ &attribute_metaclass feature of Class::MOP::Class
+
0.04 Fri Feb. 3, 2006
* Class::MOP::Class
- some documentation suggestions from #perl6
return $instance;
}
+sub attribute_metaclass { 'ClassEncapsulatedAttributes::Attribute' }
+
package # hide the package from PAUSE
ClassEncapsulatedAttributes::Attribute;
sub meta { ClassEncapsulatedAttributes->initialize($_[0]) }
- Foo->meta->add_attribute(
- ClassEncapsulatedAttributes::Attribute->new('foo' => (
- accessor => 'Foo_foo',
- default => 'init in FOO'
- ))
- );
+ Foo->meta->add_attribute('foo' => (
+ accessor => 'Foo_foo',
+ default => 'init in FOO'
+ ));
sub new {
my $class = shift;
our @ISA = ('Foo');
# duplicate the attribute name here
- Bar->meta->add_attribute(
- ClassEncapsulatedAttributes::Attribute->new('foo' => (
- accessor => 'Bar_foo',
- default => 'init in BAR'
- ))
- );
+ Bar->meta->add_attribute('foo' => (
+ accessor => 'Bar_foo',
+ default => 'init in BAR'
+ ));
# ... later in other code ...
return $instance;
}
+sub attribute_metaclass { 'InsideOutClass::Attribute' }
+
package # hide the package from PAUSE
InsideOutClass::Attribute;
sub meta { InsideOutClass->initialize($_[0]) }
- __PACKAGE__->meta->add_attribute(
- InsideOutClass::Attribute->new('foo' => (
- reader => 'get_foo',
- writer => 'set_foo'
- ))
- );
+ __PACKAGE__->meta->add_attribute('foo' => (
+ reader => 'get_foo',
+ writer => 'set_foo'
+ ));
sub new {
my $class = shift;
use Class::MOP::Attribute;
use Class::MOP::Method;
-our $VERSION = '0.04';
+our $VERSION = '0.05';
sub import {
shift;
use Sub::Name 'subname';
use B 'svref_2object';
-our $VERSION = '0.01';
+our $VERSION = '0.02';
# Self-introspection
## Methods
+# un-used right now ...
+sub method_metaclass { 'Class::MOP::Method' }
+
sub add_method {
my ($self, $method_name, $method) = @_;
(defined $method_name && $method_name)
## Attributes
+sub attribute_metaclass { 'Class::MOP::Attribute' }
+
sub add_attribute {
- my ($self,$attribute) = @_;
- (blessed($attribute) && $attribute->isa('Class::MOP::Attribute'))
- || confess "Your attribute must be an instance of Class::MOP::Attribute (or a subclass)";
+ my $self = shift;
+ # either we have an attribute object already
+ # or we need to create one from the args provided
+ my $attribute = blessed($_[0]) ? $_[0] : $self->attribute_metaclass->new(@_);
+ # make sure it is derived from the correct type though
+ ($attribute->isa('Class::MOP::Attribute'))
+ || confess "Your attribute must be an instance of Class::MOP::Attribute (or a subclass)";
$attribute->attach_to_class($self);
$attribute->install_accessors();
$self->{'%:attrs'}->{$attribute->name} = $attribute;
=over 4
+=item B<method_metaclass>
+
=item B<add_method ($method_name, $method)>
This will take a C<$method_name> and CODE reference to that
=over 4
+=item B<attribute_metaclass>
+
=item B<add_attribute ($attribute_name, $attribute_meta_object)>
This stores a C<$attribute_meta_object> in the B<Class::MOP::Class>
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 27;
+use Test::Exception;
+
+BEGIN {
+ use_ok('Class::MOP', ':universal');
+}
+
+{
+ package Point;
+
+ Point->meta->add_attribute('$.x' => (
+ reader => 'x',
+ init_arg => 'x'
+ ));
+
+ Point->meta->add_attribute('$.y' => (
+ accessor => 'y',
+ init_arg => 'y'
+ ));
+
+ sub new {
+ my $class = shift;
+ bless $class->meta->construct_instance(@_) => $class;
+ }
+
+ sub clear {
+ my $self = shift;
+ $self->{'$.x'} = 0;
+ $self->{'$.y'} = 0;
+ }
+
+ package Point3D;
+ our @ISA = ('Point');
+
+ Point3D->meta->add_attribute('$:z' => (
+ default => 123
+ ));
+
+ sub clear {
+ my $self = shift;
+ $self->{'$:z'} = 0;
+ $self->SUPER::clear();
+ }
+}
+
+isa_ok(Point->meta, 'Class::MOP::Class');
+isa_ok(Point3D->meta, 'Class::MOP::Class');
+
+# ... test the classes themselves
+
+my $point = Point->new('x' => 2, 'y' => 3);
+isa_ok($point, 'Point');
+
+can_ok($point, 'x');
+can_ok($point, 'y');
+can_ok($point, 'clear');
+
+{
+ my $meta = $point->meta;
+ is($meta, Point->meta(), '... got the meta from the instance too');
+}
+
+is($point->y, 3, '... the $.y attribute was initialized correctly through the metaobject');
+
+$point->y(42);
+is($point->y, 42, '... the $.y attribute was set properly with the accessor');
+
+is($point->x, 2, '... the $.x attribute was initialized correctly through the metaobject');
+
+$point->x(42);
+is($point->x, 2, '... the $.x attribute was not altered');
+
+$point->clear();
+
+is($point->y, 0, '... the $.y attribute was cleared correctly');
+is($point->x, 0, '... the $.x attribute was cleared correctly');
+
+my $point3d = Point3D->new('x' => 1, 'y' => 2, '$:z' => 3);
+isa_ok($point3d, 'Point3D');
+isa_ok($point3d, 'Point');
+
+{
+ my $meta = $point3d->meta;
+ is($meta, Point3D->meta(), '... got the meta from the instance too');
+}
+
+can_ok($point3d, 'x');
+can_ok($point3d, 'y');
+can_ok($point3d, 'clear');
+
+is($point3d->x, 1, '... the $.x attribute was initialized correctly through the metaobject');
+is($point3d->y, 2, '... the $.y attribute was initialized correctly through the metaobject');
+is($point3d->{'$:z'}, 3, '... the $:z attribute was initialized correctly through the metaobject');
+
+{
+ my $point3d = Point3D->new();
+ isa_ok($point3d, 'Point3D');
+
+ is($point3d->x, undef, '... the $.x attribute was not initialized');
+ is($point3d->y, undef, '... the $.y attribute was not initialized');
+ is($point3d->{'$:z'}, 123, '... the $:z attribute was initialized correctly through the metaobject');
+
+}
sub meta { InsideOutClass->initialize($_[0]) }
- Foo->meta->add_attribute(
- InsideOutClass::Attribute->new('foo' => (
- accessor => 'foo',
- predicate => 'has_foo',
- ))
- );
+ Foo->meta->add_attribute('foo' => (
+ accessor => 'foo',
+ predicate => 'has_foo',
+ ));
- Foo->meta->add_attribute(
- InsideOutClass::Attribute->new('bar' => (
- reader => 'get_bar',
- writer => 'set_bar',
- default => 'FOO is BAR'
- ))
- );
+ Foo->meta->add_attribute('bar' => (
+ reader => 'get_bar',
+ writer => 'set_bar',
+ default => 'FOO is BAR'
+ ));
sub new {
my $class = shift;
sub meta { ClassEncapsulatedAttributes->initialize($_[0]) }
- Foo->meta->add_attribute(
- ClassEncapsulatedAttributes::Attribute->new('foo' => (
- accessor => 'foo',
- predicate => 'has_foo',
- default => 'init in FOO'
- ))
- );
+ Foo->meta->add_attribute('foo' => (
+ accessor => 'foo',
+ predicate => 'has_foo',
+ default => 'init in FOO'
+ ));
- Foo->meta->add_attribute(
- ClassEncapsulatedAttributes::Attribute->new('bar' => (
- reader => 'get_bar',
- writer => 'set_bar',
- default => 'init in FOO'
- ))
- );
+ Foo->meta->add_attribute('bar' => (
+ reader => 'get_bar',
+ writer => 'set_bar',
+ default => 'init in FOO'
+ ));
sub new {
my $class = shift;
package Bar;
our @ISA = ('Foo');
- Bar->meta->add_attribute(
- ClassEncapsulatedAttributes::Attribute->new('foo' => (
- accessor => 'foo',
- predicate => 'has_foo',
- default => 'init in BAR'
- ))
- );
+ Bar->meta->add_attribute('foo' => (
+ accessor => 'foo',
+ predicate => 'has_foo',
+ default => 'init in BAR'
+ ));
- Bar->meta->add_attribute(
- ClassEncapsulatedAttributes::Attribute->new('bar' => (
- reader => 'get_bar',
- writer => 'set_bar',
- default => 'init in BAR'
- ))
- );
+ Bar->meta->add_attribute('bar' => (
+ reader => 'get_bar',
+ writer => 'set_bar',
+ default => 'init in BAR'
+ ));
sub SUPER_foo { (shift)->SUPER::foo(@_) }
sub SUPER_has_foo { (shift)->SUPER::foo(@_) }