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

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.