The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Simo - Very simple framework for Object Oriented Perl.

VERSION

Version 0.05_07

FEATURES

Simo is framework that simplify Object Oriented Perl.

The feature is that

1. You can define accessors in very simple way.
2. Overridable new method is prepared.
3. You can define default value of attribute.
4. Simo is very small. so You can install and excute it very fast.

If you use Simo, you are free from bitter work writing new and accessors repeatedly.

SYNOPSIS

Define class and accessors.

    package Book;
    use Simo;
    
    # define accessors
    sub title{ ac }
    
    # define default value
    sub author{ ac default => 'Kimoto' }
    
    # define constrain subroutine
    sub price{ ac constrain => sub{ /^\d+$/ } } # price must be integer.

    # define filter subroutine
    sub description{ ac filter => sub{ uc } } # convert to upper case.

    # define trigger subroutine
    sub issue_datetime{ ac trigger => \&update_issue_date }
    sub issue_date{ ac } # if issue_datetime is updated, issue_date is updated.
    
    sub update_issue_date{
        my $self = shift;
        my $date = substr( $self->issue_datetime, 0, 10 );
        $self->issue_date( $date );
    }
    
    # read only accessor
    sub get_size{ ac default => 5, read_only => 1 }
    
    1;

Using class and accessors

    use strict;
    use warnings;
    use Book;

    # create object
    my $book = Book->new( title => 'OO tutorial' );

    # get attribute
    my $author = $book->author;

    # set attribute
    $book->author( 'Ken' );

    # constrain( If try to set illegal value, this call will die )
    $book->price( 'a' ); 

    # filter ( convert to 'IT IS USEFUL' )
    $book->description( 'It is useful' );

    # trigger( issue_date is updated '2009-01-01' )
    $book->issue_datetime( '2009-01-01 12:33:45' );
    my $issue_date = $book->issue_date;
    
    # read only accessor
    $book->get_size;

DESCRIPTION

Define class and accessors

You can define class and accessors in simple way.

new method is automatically created, and title accessor is defined.

    package Book;
    use Simo;

    sub title{ ac }
    1;

Using class and accessors

You can pass key-value pairs to new, and can get and set value.

    use Book;
    
    # create object
    my $book = Book->new(
        title => 'OO tutorial',
    );
    
    # get value
    my $title = $book->title;
    
    # set value
    $book->title( 'The simplest OO' );

Automatically array convert

If you pass array to accessor, array convert to array ref.

    $book->title( 'a', 'b' );
    $book->title; # get [ 'a', 'b' ], not ( 'a', 'b' )

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' }

set_hook option

set_hook option is now not recommended. this option will be deleted in future 2019/01/01

get_hook option

get_hook option is now not recommended. this option will be deleted in future 2019/01/01

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'

FUNCTIONS

ac

ac is exported. This is used by define accessor.

new

orveridable new method.

MORE TECHNIQUES

I teach you useful techniques.

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.

CAUTION

set_hook and get_hook option is now not recomended. these option will be deleted in future 2019/01/01

and non named defalut value definition is not recommended. this expression cannot be available in future 2019/01/01

    sub title{ ac 'OO tutorial' } # not recommend. cannot be available in future.

AUTHOR

Yuki Kimoto, <kimoto.yuki at gmail.com>

BUGS

Please report any bugs or feature requests to bug-simo at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Simo. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Simo

You can also look for information at:

SEE ALSO

Class::Accessor,Class::Accessor::Fast, Moose, Mouse.

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.