NAME
Object::Simple - Light Weight Minimal Object System
VERSION
Version 2.0101
FEATURES
- 1. You can define accessors in very simple way.
- 2. new method is prepared.
- 3. You can define variouse accessor option(default, type, chained, weak)
- 4. you can use Mixin system like Ruby
If you use Object::Simple, you are free from bitter work writing new and accessors repeatedly.
SYNOPSIS
# Class definition( Book.pm )
package Book;
use Object::Simple;
sub title : Attr {}
sub author : Attr {}
sub price : Attr {}
Object::Simple->build_class; # End of module. Don't forget to call 'build_class' method
# Using class
use Book;
my $book = Book->new(title => 'a', author => 'b', price => 1000);
# Default value
sub author : Attr { default => 'Kimoto' }
#Automatically build
sub author : Attr { auto_build => 1 }
sub build_author{
my $self = shift;
$self->author( $self->title . "b" );
}
# Read only accessor
sub year : Attr { read_only => 1 }
# weak reference
sub parent : Attr { weak => 1 }
# method chaine
sub title : Attr { chained => 1 }
# variable type
sub authors : Attr { type => 'array' }
sub country : Attr { type => 'hash' }
# convert to object
sub url : Attr { convert => 'URI' }
sub url : Attr { convert => sub{ ref $_[0] ? $_[0] : URI->new($_[0]) } }
# derefference of returned value
sub authors : Attr { type => 'array', deref => 1 }
sub country_id : Attr { type => 'hash', deref => 1 }
# trigger option
sub error : Attr { trigger => sub{ $_[0]->state('error') } }
sub state : Attr {}
# define accessor for class variable
sub options : ClassAttr {
type => 'array',
auto_build => sub { shift->options([]) }
}
# define translate accessor
sub person : Attr { default => sub{ Person->new } }
sub name : Translate { target => 'person->name' }
sub age : Translate { target => 'person->age' }
# define accessor to output attribute value
sub errors : Attr {}
sub errors_to : Output { target => 'errors' }
# Inheritance
package Magazine;
use Object::Simple( base => 'Book' );
# Mixin
package Book;
use Object::Simple(
mixins => [
'Object::Simple::Mixin::AttrNames',
'Object::Simple::Mixin::AttrOptions'
]
);
METHODS
new
new is prepared.
use Book;
my $book = Book->new( title => 'a', author => 'b', price => 1000 );
This new can be overided.
# initialize object
sub new {
my $self = shift->SUPER::new(@_);
# initialize object
return $self;
}
# arrange arguments
sub new {
my ($self, @args) = @_;
my $self = $self->SUPER::new(title => $_[0], author => $_[1]);
return $self;
}
build_class
inherit base class,include mixin classes, create accessors, and create constructor
Script must call build_class at end of script;
Object::Simple->build_class;
The class of caller package is build.
You can also specify class
Object::Simple->build_class('SomeClass');
build_all_classes
You can build all classes once.
Object::Simple->build_all_classes;
resist_attribute_info
resist attribute information
Object::Simple->resist_attribute_info($class, $attr_name, $code_ref, $code_attribute_type);
Object::Simple->resist_attribute_info('Book', 'title', sub {default => 1}, 'Attr');
This is equal to
package Book;
sub title : Attr {default => 1}
If you create accessor, you must call build_class
Object::Simple->build_class('Book');
ACCESSOR OPTIONS
default
You can define attribute default value.
sub title : Attr {default => 'Good news'}
If you define default values using reference or Object, you need wrapping it by sub{}.
sub authors : Attr { default => sub{['Ken', 'Taro']} }
auto_build
When accessor is called first,a methods is called to build attribute.
sub author : Attr { auto_build => 1 }
sub build_author{
my $self = shift;
$self->atuhor( Person->new );
}
Builder method name is build_ATTRIBUTE_NAME by default;
You can specify build method .
sub author : Attr { auto_build => 1 }
sub create_author{
my $self = shift;
$self->atuhor( Person->new );
}
read_only
You can create read only accessor
sub title: Attr { read_only => 1 }
chained
Setter return value is self by default. So you can do method chain.
$book->title('aaa')->author('bbb')->...
If you do not use method chain,You do following.
sub title : Attr { chained => 0 }
sub author : Attr { chained => 0 }
Setter retrun value is current value;
my $current_value = $book->title('aaa');
weak
attribute value is weak reference.
sub parent : Attr {weak => 1}
type
You can specify variable type( array, hash );
# variable type
sub authors : Attr { type => 'array' }
sub country_id : Attr { type => 'hash' }
If you specity 'array', arguments is automatically converted to array reference
$book->authors('ken', 'taro'); # ('ken', 'taro') -> ['ken', 'taro']
$book->authors('ken'); # ('ken') -> ['ken']
If you specity 'hash', arguments is automatically converted to hash reference
$book->country_id(Japan => 1); # (Japan => 1) -> {Japan => 1}
convert
You can convert a non blessed scalar value to object.
sub url : Attr { convert => 'URI' }
$book->url('http://somehost'); # convert to URI->new('http://somehost')
You can also convert a scalar value using your convert function.
sub url : Attr { convert => sub{ ref $_[0] ? $_[0] : URI->new($_[0]) } }
deref
You can derefference returned value.You must specify it with 'type' option.
sub authors : Attr { type => 'array', deref => 1 }
sub country_id : Attr { type => 'hash', deref => 1 }
my @authors = $book->authors;
my %country_id = $book->country_id;
trigger
You can defined trigger function when value is set.
sub error : Attr { trigger => sub{ $_[0]->stete('error') } }
sub state : Attr {}
extend
You can extend super class accessor options. If you overwrite only default value, do the following
package BaseClass
use Object::Simple;
sub authors { default => sub {['taro', 'ken']}, array => 1, deref => 1 }
Object::Simple->build_class;
package SomeClass
use Object::Simple(base => 'BaseClass');
sub authors { extend => 1, default => sub {['peter', 'miki']} }
Object::Simple->build_class;
SPECIAL ACCESSOR
ClassAttr - Accessor for class variable
You can also define accessor for class variable.
# class attribute accessor
sub options : ClassAttr {
type => 'array',
auto_build => sub { shift->options([]) }
}
options set or get class variable, not some instance.
you can use the same accessor options as normal accessor except 'default' option.
If you define default value to class variable, you must use 'auto_build' option.
If this accessor is used subclass, it access subclass class variable, not the class it is defined.
Output - Accessor to output attribute value
You can define accessor to output attribute value
# define accessor to output attribute value
sub errors : Attr {}
sub errors_to : Output { target => 'errors' }
sub results : Attr {}
sub results_to : Output { target => 'results' }
This accessor is used the following way.
Create instance and Set input file and parse. parse method save the parsed results to results attribute and some errors to errors attribute and continuasly get resutls to $results variable and get errors to $errors variable.
use SomeParser;
SomeParser
->new
->input_file('somefile')
->parse
->results_to(\my $results)
->errors_to(\my $errors)
;
You are not familiar with this style. But this style is very beautiful and write a soruce code without duplication. And You can get rid of typo in source code.
Translate - Accessor to convert to other accessor
You can define accessor shortcut of object of other attribute value.
sub person : Attr { default => sub{ Person->new } }
sub name : Attr { translate => 'person->name' }
sub age : Attr { translate => 'person->age' }
You can accesse person->name when you call name.
INHERITANCE
# Inheritance
package Magazine;
use Object::Simple( base => 'Book' );
Object::Simple do not support multiple inheritance because it is so complex.
MIXIN
Object::Simple support mixin syntax
# Mixin
package Book;
use Object::Simple(
mixins => [
'Object::Simple::Mixin::AttrNames',
'Object::Simple::Mixin::AttrOptions'
]
);
Object::Simple mixin merge mixin class attribute.
# mixin class
package Some::Mixin;
use Object::Simple;
sub m2 : Attr {}
Object::Simple->build_class;
# using mixin class
package Some::Class;
use Object::Simple( mixins => [ 'Some::Mixin' ] );
sub m1 : Attr {}
Object::Simple->build_class;
Because Some::Mixin is mixined, Some::Class has two attribute m1 and m2.
METHODS SEARCHING ORDER
Method searching order is like Ruby.
If method names is crashed, method search order is the following
1. This class
2. Mixin class2
3. Mixin class1
4. Base class
+--------------+
4 | Base class |
+--------------+
|
+--------------+
3 | Mixin class1 |
+--------------+
|
+--------------+
2 | Mixin class2 |
+--------------+
|
+--------------+
1 | This class |
+--------------+
# 1
package ThisClass;
# 4 3 2
Object::Simple(base => 'BaseClass', mixins => ['MixinClass1', 'MixinClass2']);
CALLING MIXINS METHODS
CALL ALL MIXINS METHODS
You can call all methods of mixins methods.
$self->Object::Simple::MIXINS::initialize; # call all initialize of mixin classes
$self->Object::Simple::MIXINS::DESTROY; # call all DESTROY of mixin classes
$self->Object::Simple::MIXINS::method; # any method ok!
For example, you can call all initialize methods of mixin classes package ThisClass; Object::Simple(mixins => ['MixinClass1', 'MixinClass2']);
sub initialize {
my $self = shift;
# call initialize of all mixin class
$self->Object::Simple::MIXINS::initialize;
}
CALL UPPER CLASS METHODS
You can call upper methods.
$self->Object::Simple::UPPER::method;
Method is searched by the following order and call the method.
1. Mixin class2
2. Mixin class1
3. Base class
package ThisClass;
Object::Simple(base => 'BaseClass', mixins => ['MixinClass1', 'MixinClass2']);
sub run {
my $self = shift;
$self->Object::Simple::UPPER::run;
}
If MixinClass1 have run methods, MixinClass1::run is called.
If MIxinClass1 and MixinClass2 have run method, MixinClass2::run is called.
using your MODIFY_CODE_ATTRIBUTES subroutine
Object::Simple define own MODIFY_CODE_ATTRIBUTES subroutine. If you use your MODIFY_CODE_ATTRIBUTES subroutine, do 'no Object::Simple;'
package T19;
use Object::Simple;
sub m1 : Attr {}
no Object::Simple; # unimport MODIFY_CODE_ATTRIBUTES
# defined MODIFY_CODE_ATTRIBUTES
sub MODIFY_CODE_ATTRIBUTES {
my ($class, $ref, @attrs) = @_;
# do what you want
return;
}
sub m2 : YourAttribute {}
Object::Simple->build_class;
AUTHOR
Yuki Kimoto, <kimoto.yuki at gmail.com>
I develope in http://github.com/yuki-kimoto/
SIMILAR MODULES
Class::Accessor,Class::Accessor::Fast, Moose, Mouse, Mojo::Base
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.