Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to create a class attribute in Moose?

Tags:

perl

moose

I need a class attribute in Moose. Right now I am saying:

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;
use MooseX::Declare;

class User {
    has id      => (isa => "Str", is => 'ro', builder => '_get_id');
    has name    => (isa => "Str", is => 'ro');
    has balance => (isa => "Num", is => 'rw', default => 0);

    #FIXME: this should use a database  
    method _get_id {
        state $id = 0; #I would like this to be a class attribute
        return $id++;
    }
}

my @users;
for my $name (qw/alice bob charlie/) {
    push @users, User->new(name => $name);
};

for my $user (@users) {
    print $user->name, " has an id of ", $user->id, "\n";
}
like image 970
Chas. Owens Avatar asked Jun 29 '09 01:06

Chas. Owens


2 Answers

I found MooseX::ClassAttribute, but it looks ugly. Is this the cleanest way?

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;
use MooseX::Declare;

class User {
    use MooseX::ClassAttribute;

    class_has id_pool => (isa => "Int", is => 'rw', default => 0);

    has id      => (isa => "Str", is => 'ro', builder => '_get_id');
    has name    => (isa => "Str", is => 'ro');
    has balance => (isa => "Num", is => 'rw', default => 0);

    #FIXME: this should use a database  
    method _get_id {
        return __PACKAGE__->id_pool(__PACKAGE__->id_pool+1);
    }
}

my @users;
for my $name (qw/alice bob charlie/) {
    push @users, User->new(name => $name);
};

for my $user (@users) {
    print $user->name, " has an id of ", $user->id, "\n";
}
like image 162
Chas. Owens Avatar answered Oct 17 '22 21:10

Chas. Owens


Honestly, I don't think it's necessary to all that trouble for class attributes. For read-only class attributes, I just use a sub that returns a constant. For read-write attributes, a simple state variable in the package usually does the trick (I haven't yet run into any scenarios where I needed something more complicated.)

state $count = 0;
method _get_id { 
    return ++$count;
}

A private block with a lexical can be used if you need pre-5.10 compatibility.

like image 31
friedo Avatar answered Oct 17 '22 19:10

friedo