NAME

Object::Simple - generate accessor with default, and provide constructor

VERSION

Version 3.0607

SYNOPSIS

package YourClass;

use base 'Object::Simple';

# Generate accessor
__PACKAGE__->attr('x');

# Generate accessor with default (scalar)
__PACKAGE__->attr(x => 0);

# Generate accessor with default (reference or instance)
__PACKAGE__->attr(x => sub { [] });
__PACKAGE__->attr(x => sub { {} });
__PACKAGE__->attr(x => sub { SomeClass->new });

# Generate accessors at once
__PACKAGE__->attr([qw/x y z/]);

# Generate accessors with default at once
__PACKAGE__->attr([qw/x y z/] => 0);

# Generate class accessor
__PACKAGE__->class_attr('x');
__PACKAGE__->class_attr(x => 0);

# Generate inheritable class accessor
__PACKAGE__->class_attr('x', default => 0, inherit => 'scalar_copy');
__PACKAGE__->class_attr('x', default => sub { [] }, inherit => 'array_copy');
__PACKAGE__->class_attr('x', default => sub { {} }, inherit => 'hash_copy');

__PACKAGE__->class_attr(
  'x', default => sub { SomeClass->new }, inherit => sub { shift->clone });

# Generate dual accessor, which work as normal accessor or class accessor
__PACKAGE__->dual_attr('x');
__PACKAGE__->dual_attr(x => 0);

# Generate inheritable dual accessor
__PACKAGE__->dual_attr('x', default => 0, inherit => 'scalar_copy');
__PACKAGE__->dual_attr('x', default => sub { [] }, inherit => 'array_copy');
__PACKAGE__->dual_attr('x', default => sub { {} }, inherit => 'hash_copy');

__PACKAGE__->dual_attr(
  'x', default => sub { SomeClass->new }, inherit => sub { shift->clone });

package main;

# Constructor new()
my $obj = YourClass->new;
my $obj = YourClass->new(x => 1, y => 2);
my $obj = YourClass->new({x => 1, y => 2});

# Set attribute
$obj->x(1);

# Setter method chain is available
$obj->x(1)->y(2);

# Get attribute
my $x = $obj->x;

DESCRIPTION

introduction

Object::Simple is the generator of accessor. If you want to create a class, you must write many accessors by yourself, so you will be tired of writing accesors.

Object::Simple help you to create accessor. You can call attr() method to create accessor from subclass of Object::Simple

package YourClass;

use base 'Object::Simple';

# Generate accessor
__PACKAGE__->attr('x');

Object::Simple also provide constructor new(). new() can receive hash or hash reference.

# Constructor new()
my $obj = YourClass->new(x => 1, y => 2);
my $obj = YourClass->new({x => 1, y => 2});

This instance can call x() to set and get attribute.

# Set attribute
$obj->x(1);

# Get attribute
my $x = $obj->x;

Default value for accessor can be specified. If x() is called at first, the default value is set to the attribute.

# Generate accessor with default (scalar)
__PACKAGE__->attr(x => 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(x => sub { [] });
__PACKAGE__->attr(x => sub { {} });
__PACKAGE__->attr(x => sub { SomeClass->new });

examples

I wrote 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);
}

how to override new()

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

import accessor generating methods

You can only import accessor generating methods if you need.

package YourClass;

use Object::Simple qw/attr class_attr dual_attr/;

__PACKAGE__->attr('x');

implementation

attr(), class_attr(), and dual_attr() is implemented by closure, not eval, so memory efficiency is very good. and the performance of compiling is very fast.

And accessor is optimized not to damage the performance.

Object::Simple pay attention to usability. If wrong number arguments is passed to new() or accessor, exception is thrown.

# Exception!
my $obj = YourClass->new(1); 

# Exception!
$obj->x(a => 1);

history

Class::Accessor::Fast is very useful. so I wanted to add new new features to that. But when I looked at Mojo::Base, I realized that it is not necessarily to have many features to do Object Oriented Programing.

So I decided that Object::Simple has compatible of Mojo::Base. Mojo::Base is minimal but enough to do Object Oriented Programing.

METHODS

new

Create instance. the subclass of Object::Simple inherit new() method. "new" receive hash or hash reference.

package YourClass;

use base 'Object::Simple';

my $obj = YourClass->new;
my $obj = YourClass->new(x => 1, y => 2);
my $obj = YourClass->new({x => 1, y => 2});

attr

Generate accessor.

__PACKAGE__->attr('x');
__PACKAGE__->attr([qw/x y z/]);

You can specify default value for accessor.

__PACKAGE__->attr(x => 0);
__PACKAGE__->attr([qw/x y z/] => 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.

__PACKAGE__->attr(x => sub { [] });
__PACKAGE__->attr(x => sub { {} });
__PACKAGE__->attr(x => sub { SomeClass->new });

Setter is chained.

$obj->x(3)->y(4);

class_attr

Generate class accessor.

__PACKAGE__->class_attr('x');
__PACKAGE__->class_attr(x => 0);
__PACKAGE__->class_attr([qw/x y z/]);

Class accessor is called by class, not instance.

YourClass->x(5);

The value is saved to $CLASS_ATTRS in that class.

If you want to delete the value or check the existence it, "delete" or "exists" function is available.

delete $YourClass::CLASS_ATTRS->{x};
exists $YourClass::CLASS_ATTRS->{x};

If you call class accessor from subclass, the value is saved to $CLASS_ATTRS in the subclass.

# The value is saved to $YourSubClass::CLASS_ATTRS
YourSubClass->x(6); 

Class accessor can inherit the value of class variable in super class.

__PACKAGE__->class_attr('x', default => 0, inherit => 'scalar_copy');
__PACKAGE__->class_attr('x', default => sub { [] }, inherit => 'array_copy');
__PACKAGE__->class_attr('x', default => sub { {} }, inherit => 'hash_copy');

dual_attr

Generate dual accessor, which work as normal accessor or class accessor.

__PACKAGE__->class_attr('x');
__PACKAGE__->class_attr(x => 0);
__PACKAGE__->class_attr([qw/x y z/]);

Accessor is called both by instance and class. If called by instance, the accessor work as normal accessor. If called by class, the accessor work as class accessor.

$obj->x(5)
YourClass->x(5);

Dual accessor can inherit the value of class variable if called by instance, and the value of class variable in super class if called by class.

__PACKAGE__->class_attr('x', default => 0, inherit => 'scalar_copy');
__PACKAGE__->class_attr('x', default => sub { [] }, inherit => 'array_copy');
__PACKAGE__->class_attr('x', default => sub { {} }, inherit => 'hash_copy');

STABILITY

Object::Simple is stable. APIs and the implementation will not be changed from v3.0601. Only bug fixing will be done if it is 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.