Вы можете попробовать Moose (или Mouse или Any :: Moose ).
package TAG;
use Moose;
has ID => (
reader => 'getID', # this is the only one that is needed
writer => 'setID',
predicate => 'hasID',
clearer => 'clearID',
isa => 'Str', # this makes setID smarter
required => 1, # forces it to be included in new
);
has name => (
is => 'ro', # same as reader => 'name',
required => 1, # forces it to be included in new
);
# Notice that you don't have to make your own constructor.
# In fact, if you did, you would effectively break Moose
# so don't do that.
Хотя это на самом деле не мешает TAG->{ID}
доступу, но делает несколько вещей для вас изнутри.
Что примерно эквивалентно:
package TAG;
use strict;
use warnings;
sub getID{
my($self) = @_;
return $self->{ID};
}
sub setID{
my($self,$new_id) = @_;
# die if $new_id is anything other than a string
# ( the one produced by Moose is smarter )
die if ref $new_id;
die unless defined $new_id;
$self->{ID} = $new_id
}
sub hasID{
my($self) = @_;
return exists $self->{ID}
}
sub clearID{
my($self) = @_;
delete $self->{ID}
}
sub name{
my($self) = @_;
return $self->{name}
}
# The constructor provided by Moose is vastly superior
# to the one shown here.
sub new{
my($class,%opt) = @_;
my $self = bless {}, $class;
die unless exists $opt{ID}; # this was the required => 1, from above
$self->setID($opt{ID});
die unless exists $opt{name}; # this was the required => 1, from above
$self->{name} = $opt{name};
}
Существует теория, согласно которой число ошибок в данном фрагменте кода пропорционально количеству строк кода.
Если это так, то я бы сказал, что в версии Moose значительно меньше ошибок.
На самом деле, если бы я реализовал все, что Moose делает для вас, было бы более чем в два раза больше строк кода, чем сейчас.
Если вы действительно нуждаетесь в для предотвращения доступа $TAG->{ID}
, вы можете использовать другой метакласс, все еще используя Moose . Не спрашивайте меня, как это сделать, я только недавно начал использовать Moose .