NAME
Object::Simple - Generate accessor having default value, and provide constructor
SYNOPSIS
Class definition.
package SomeClass;
use base 'Object::Simple';
# Generate accessor
__PACKAGE__->attr('foo');
# Generate accessor with default
__PACKAGE__->attr(foo => 0);
__PACKAGE__->attr(foo => sub { [] });
__PACKAGE__->attr(foo => sub { {} });
__PACKAGE__->attr(foo => sub { OtherClass->new });
# Generate accessors at once
__PACKAGE__->attr([qw/foo bar baz/]);
__PACKAGE__->attr([qw/foo bar baz/] => 0);
Use the class
# Constructor
my $obj = SomeClass->new(foo => 1, bar => 2);
my $obj = SomeClass->new({foo => 1, bar => 2});
# Get attribute
my $foo = $obj->foo;
# Set attribute
$obj->x(1);
Class accessor. Accessor for class variable.
# Generate class accessor
__PACKAGE__->class_attr('foo');
__PACKAGE__->class_attr(foo => 0);
# Generate inheritable class accessor
__PACKAGE__->class_attr(
'foo', default => 0, inherit => 'scalar_copy');
__PACKAGE__->class_attr(
'foo', default => sub { [] }, inherit => 'array_copy');
__PACKAGE__->class_attr(
'foo', default => sub { {} }, inherit => 'hash_copy');
__PACKAGE__->class_attr(
'foo',
default => sub { OtherClass->new },
inherit => sub { shift->clone }
);
Dual accessor. Accessor for both object and class variable.
# Generate dual accessor
__PACKAGE__->dual_attr('foo');
__PACKAGE__->dual_attr(foo => 0);
# Generate inheritable dual accessor
__PACKAGE__->dual_attr(
'foo', default => 0, inherit => 'scalar_copy');
__PACKAGE__->dual_attr(
'foo', default => sub { [] }, inherit => 'array_copy');
__PACKAGE__->dual_attr(
'foo', default => sub { {} }, inherit => 'hash_copy');
__PACKAGE__->dual_attr(
'foo',
default => sub { OtherClass->new },
inherit => sub { shift->clone }
);
DESCRIPTIONS
1. Features
Object::Simple is a generator of accessor, such as Class::Accessor, Mojo::Base, or Moose Class::Accessor is simple, but it lack offten used features. new()
method can't receive hash arguments. Default value can't be specified to accessor generating method. If multipul value is set by accssor, its value is converted to array reference without warnings.
Moose is so complex for many people to use, and depend on many modules. This is almost another language, not fit familiar perl syntax. Moose increase the complexity of projects, rather than increase production eficiency. In addition, its complie speed is slow and the used memroy is huge.
Object::Simple is the middle area between Class::Accessor and complex class builder. Only offten used features is implemnted. This module is compatible of Mojo::Base for many people to use easily. You can define default value for accessor, and define class accessor. This is like Class::Data::Inheritable, but more useful because you can specify method to copy the value of super class. Compile speed is fast and the used memory is small. Debuggin is easy.
2. Basic usage
package SomeClass;
use base 'Object::Simple';
__PACKAGE__->attr('foo');
Object::Simple also provide a constructor. new() receive hash or hash reference.
# Constructor
my $obj = SomeClass->new(foo => 1, bar => 2);
my $obj = SomeClass->new({foo => 1, bar => 2});
This instance can call x() to set and get attribute.
# Set attribute
$obj->foo(1);
# Get attribute
my $foo = $obj->foo;
Default value for accessor can be specified. If foo()
is called at first, the default value is set to the attribute.
# Generate accessor with default
__PACKAGE__->attr(foo => 0);
If you specifiy a reference or instance as default value, it must be return value of sub reference. This is requirement not to share the value with more than one instance.
# Generate accessor with default (reference or instance)
__PACKAGE__->attr(foo => sub { [] });
__PACKAGE__->attr(foo => sub { {} });
__PACKAGE__->attr(foo => sub { SomeClass->new });
I wrote some examples, Point and Point3D class. Point has two accessor x() and y(), and method clear().
Point3D is subclass of Point. Point3D has three accessor x(), y(), z(), and method clear() which is overridden.
package Point;
use strict;
use warnings;
use base 'Object::Simple';
__PACKAGE__->attr(x => 0);
__PACKAGE__->attr(y => 0);
sub clear {
my $self = shift;
$self->x(0);
$self->y(0);
}
package Point3D;
use strict;
use warnings;
use base 'Point';
__PACKAGE__->attr(z => 0);
sub clear {
my $self = shift;
$self->SUPER::clear();
$self->z(0);
}
You can override new() to initialize the instance or arrange arguments. To call super class new(), you can use SUPER pseudo-class.
Initialize instance:
sub new {
my $self = shift->SUPER::new(@_);
# Initialization
return $self;
}
Arrange arguments:
sub new {
my $self = shift;
$self->SUPER::new(x => $_[0], y => $_[1]);
return $self;
}
Object::Simple pay attention to usability. If wrong number arguments is passed to new() or accessor, exception is thrown.
# Constructor must receive even number aruments or hash refrence
my $obj = SomeClass->new(1); # Exception!
# Accessor must receive only one argument
$obj->x(a => 1); # Exception!
You can only import accessor generator method.
package SomeClass;
use Object::Simple qw/attr class_attr dual_attr/;
__PACKAGE__->attr('foo');
METHODS
new
my $obj = Object::Simple->new(foo => 1, bar => 2);
my $obj = Object::Simple->new({foo => 1, bar => 2});
Create a new object. new()
method receive hash or hash reference as arguments.
attr
Generate accessor.
__PACKAGE__->attr('foo');
__PACKAGE__->attr([qw/foo bar baz/]);
__PACKAGE__->attr(foo => 0);
__PACKAGE__->attr(foo => sub { {} });
Generate accessor. attr()
method receive two arguments, accessor name and default value. If you want to create multipul accessors at once, specify accessor names as array reference at first argument. Default value is optional. If you want to specify refrence or object as default value, the value must be sub reference not to share the value with other objects.
Generated accessor.
my $value = $obj->foo;
$obj = $obj->foo(1);
You can set and get a value. If a default value is specified and the value is not exists, you can get default value. Accessor return self object if a value is set.
class_attr
__PACKAGE__->class_attr('foo');
__PACKAGE__->class_attr([qw/foo bar baz/]);
__PACKAGE__->class_attr(foo => 0);
__PACKAGE__->class_attr(foo => sub { {} });
Generate accessor for class variable. class_attr()
method receive two arguments, accessor name and default value. If you want to create multipul accessors at once, specify accessor names as array reference at first argument. Default value is optional. If you want to specify refrence or object as default value, the value must be sub reference not to share the value with other objects.
Generated class accessor.
my $value = SomeClass->foo;
$class = SomeClass->foo(1);
You can set and get a value. If a default value is specified and the value is not exists, you can get default value. Accessor return class name if a value is set.
Class accessor save the value to the class variable "CLASS_ATTRS". The folloing two is same.
SomeClass->foo(1);
$SomeClass::CLASS_ATTRS->{foo} = 1;
You can delete the value and check existance of it.
delete $SomeClass::CLASS_ATTRS->{foo};
exists $SomeClass::CLASS_ATTRS->{foo};
If the value is set from subclass, the value is saved to the class variable of subclass.
$SubClass->foo(1);
$SubClass::CLASS_ATTRS->{foo} = 1;
If you want to inherit the value of super class, use default
and inherit
options.
__PACKAGE__->class_attr(
'foo', default => sub { {} }, inherit => 'hash_copy');
you must specify the way to copy the value of super class to inherit
option. this is one of scalar_copy
, array_copy
, hash_copy
, or sub reference.
scalar
copy is normal copy, array_copy
is surface copy of array reference hash_copy
is surface copy of hash reference. the implementations are the folloing ones.
# scalar_copy
my $copy = $value;
# array_copy
my $copy = [@{$value}];
# hash_copy
my $copy = {%{$value}};
dual_attr
__PACKAGE__->dual_attr('foo');
__PACKAGE__->dual_attr([qw/foo bar baz/]);
__PACKAGE__->dual_attr(foo => 0);
__PACKAGE__->dual_attr(foo => sub { {} });
Generate accessor for both object and class variable. dual_attr()
method receive two arguments, accessor name and default value. If you want to create multipul accessors at once, specify accessor names as array reference at first argument. Default value is optional. If you want to specify refrence or object as default value, the value must be sub reference not to share the value with other objects.
Generated dual accessor.
my $value = $obj->foo;
$obj = $obj->foo(1);
my $value = SomeClass->foo;
$class = SomeClass->foo(1);
You can set and get a value. If a default value is specified and the value is not exists, you can get default value. Accessor return class name or object if a value is set.
If accessor is called from object, the value is saved to object. If accesosr is called from class name, the value is saved to class variable. See also description of class_attr
method.
dual_attr()
method have default
and inherit
options as same as class_attr()
method have.
__PACKAGE__->dual_attr(
'foo', default => sub { {} }, inherit => 'hash_copy');
But one point is different. If accessor is called from a object, the object inherit the value of the class.
SomeClass->foo({name => 1});
my $obj = SomeClass->new;
my $foo = $obj->foo;
$foo
is {name =
1}> because it inherit the value of class.
EXPORTS
STABILITY
Object::Simple is now stable. APIs and the implementations will not be changed in the future.
BUGS
Please tell me bugs if they are found.
AUTHOR
Yuki Kimoto, <kimoto.yuki at gmail.com>
COPYRIGHT & LICENSE
Copyright 2008 Yuki Kimoto, all rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.