NAME

Simo::Manual - Simo Manual

CAUTION

Now writing.

Please wait.

DESCRIPTION

Accessor options

default option

You can define default value of attribute.

sub title{ ac default => 'Perl is very interesting' }

constrain option

you can constrain setting value.

sub price{ ac constrain => sub{ /^\d+$/ } }

For example, If you call $book->price( 'a' ), this call is die, because 'a' is not number.

'a' is set to $_. so if you can use regular expression, omit $_.

you can write not omiting $_.

sub price{ ac constrain => sub{ $_ > 0 && $_ < 3 } }

If you display your message when program is die, you call craok.

use Carp;
sub price{ ac constrain => sub{ $_ > 0 && $_ < 3 or croak "Illegal value" } }

and 'a' is alse set to first argument. So you can receive 'a' as first argument.

sub price{ ac constrain => \&_is_number }

sub _is_number{
    my $val = shift;
    return $val =~ /^\d+$/;
}

and you can define more than one constrain.

sub price{ ac constrain => [ \&_is_number, \&_is_non_zero ] }

filter option

you can filter setting value.

sub description{ ac filter => sub{ uc } }

setting value is $_ and frist argument like constrain.

and you can define more than one filter.

sub description{ ac filter => [ \&uc, \&quoute ] }

trigger option

You can define subroutine called after value is set.

For example, issue_datetime is set, issue_date is update.

$self is set to $_ and $_[0] different from constrain and filter.

sub issue_datetime{ ac trigger => \&update_issue_date }
sub issue_date{ ac }

sub update_issue_date{
    my $self = shift;
    my $date = substr( $self->issue_datetime, 0, 10 );
    $self->issue_date( $date );
}

and you can define more than one trigger.

sub issue_datetime{ ac trigger => [ \&update_issue_date, \&update_issue_time ] }

read_only option

Read only accessor is defined

sub get_size{ ac default => 5, read_only => 1 }

Accessor name should be contain 'get_'.If not, warnings is happen.

hash_force option

If you pass array to accessor, Normally list convert to array ref. $book->title( 'a' , 'b' ); # convert to [ 'a', 'b' ]

Even if you write $book->title( a => 'b' )

( a => 'b' ) converted to [ 'a', 'b' ]

If you use hash_force option, you convert list to hash ref

sub country_id{ ac hash_force => 1 }

$book->title( a => 'b' ); # convert to { a => 'b' }

Order of constrain, filter and trigger

1. val is passed to constrain subroutine.
2. val is passed to filter subroutine.
3. val is set
4. trigger subroutine is called
      |---------|   |------|                  |-------| 
      |         |   |      |                  |       | 
val-->|constrain|-->|filter|-->(val is set)-->|trigger| 
      |         |   |      |                  |       | 
      |---------|   |------|                  |-------| 

Get old value

You can get old value when you use accessor as setter.

$book->author( 'Ken' );
my $old_value = $book->author( 'Taro' ); # $old_value is 'Ken'

MORE TECHNIQUE

New method overriding

by default, new method receive key-value pairs. But you can change this action by overriding new method.

For example, Point class. You want to call new method this way.

my $point = Point->new( 3, 5 ); # xPos and yPos

You can override new method.

package Point;
use Simo;

sub new{
    my ( $self, $x, $y ) = @_; # two arg( not key-value pairs )
    
    # You can do anything if you need
    
    return $self->SUPER::new( x => $x, y => $y );
}

sub x{ ac }
sub y{ ac }
1;

Simo implement inheritable new method. Whenever You change argments or add initializetion, You override new method.

Extend base class

you may want to extend base class. It is OK.

But I should say to you that there are one thing you should know. The order of Inheritance is very important.

I write good sample and bad sample.

# base class
package Book;
sub title{ ac };

# Good sample.
# inherit base class. It is OK!
package Magazine;
use base 'Book'; # use base is first
use Simo;        # use Simo is second;

# Bad sample
package Magazine;
use Simo;          # use Simo is first
use base 'Book';   # use base is second

If you call new method in Good sample, you call Book::new method. This is what you wanto to do.

If you call new method in Bad sample, you call Simo::new method. you will think why Book::new method is not called?

Maybe, You will be wrong sometime. So I recomend you the following writing.

package Magazine; use base 'Book'; # package and base class
use Simo;                          

It is like other language class Definition and I think looking is not bat. and you are not likely to choose wrong order.

new_self_and_parent

new_self_and_parent resolve the inheritance of no Simo based class;

# no Simo based class
package Book;
sub new{
    my ( $proto, %args ) = @_;
    my $class = ref $proto || $proto;
    
    my $self = {};
    bless $self, $class;
    
    $self->{ title } = $args{ title };
    $self->{ author } = $args{ author };
    
    return $self;
}

package Magazine;
use Simo( base => 'Book' );

sub price{ ac }
sub description{ ac }

sub new{
    my ( $self, @args ) = @_;
    return $self->new_self_and_parent( @args, [ 'title', 'author' ] );