[Bioperl-l] do not hate individual getter/setters coding?
Xiao Juguang
juguang@fugu-sg.org
Wed Jan 15 08:04:24 EST 2003
Hi guys,
I may be a very lazy coder, so that I was tired on writing tedious getter/setters fragment, as well, as a source code reader, I felt bored to read individule getter/setters occupying, sometimes, more than half of module. Do you? I thought bioperl follows Perl's neat soul and Perl hopes its features to be fully used. Should we just suggest to add 2 subs in Bio::Root::Root ? _autoload_methods and AUTOLOAD . They look like this.
=head2 _autoload_methods
This subroutine is usually invoked at the very beginning line of constructor,
to set subroutine names for getter and setters.
SYNOPSIS
sub new{
my ($class, @args) = @_;
my $self = $class->SUPER::new(@args);
$self->_autoload_methods([qw(dbhost dbname dbuser dbpass)]); # Don't add if unnecessary.
# Then, say
my ($dbhost) = $self->_rearrange([qw(DBHOST)], @args);
$self->dbhost($dbhost);
return $self;
}
=cut
sub _autoload_methods {
my ($self, $arg) = @_;
if(defined $arg && ref($arg) eq 'ARRAY'){
# $self->{_autoload_methods} = $arg;
push @{$self->{_autoload_methods}}, @{$arg};
# equally explicitly declare the subs !!!
use subs @{$self->{_autoload_methods}};
}
return $self->{_autoload_methods};
}
sub AUTOLOAD{
return if our $AUTOLOAD =~ /::DESTROY$/;
my ($self, $arg) = @_;
my $field = $AUTOLOAD;
$field =~ /::([\w\d]+)$/;
if($self->_autoload_methods && grep /$1/, @{$self->_autoload_methods}){
$self->{$field} = $arg if defined $arg;
return $self->{$field};
}else{
$self->throw("Can't find the method '$field'");
}
}
I remembered in this mailing list, there was a discussion on it. However, I forgot the harm to use it that people mention. In theory, Bio::Root::Root::AUTOLOAD will be almost last visited in the path of method searching. I just quote paragraphs from Programming Perl 3rd Ed. by Larry Wall, for your information.
When your invoke a method 'methname' on an invocant of type 'classname', Perl tries six different ways to find a subroutine to use:
1. First, Perl looks in the invocant's own package for a subroutine named classname::methname. If that fails, inheritance kicks in, and we go to step 2.
2. Next, Perl checks for methods inherited from base classes by looking in all the parent packages listed in @classmane::ISA for a parent::methname subroutine. The search is left-to-right, recurive, and depth-first. The recursion assures that grandparent classes, great-grandparent classes, great-great-grandparent classes, and so on, are all searched.
3. If that fails, Perl looks for a subroutine named UNIVERSAL::methname.
4. At this point, Perl gives up on methname and starts looking for an AUTOLOAD. First, it looks for a subroutine named classname::AUTOLOAD.
5. Failing that, Perl searches all parent packages listed in @classname::ISA, for any parent::AUTOLOAD subroutine. The search is again left-to-right, recurive, and depth-first.
6. Finally, Perl looks for a subroutine named UNIVERSAL::AUTOLOAD.
Perl stops after the first successful attempt and invokes that subroutine.
To make perldoc friendly, developer should write pod for each 'virtual getter/setter' or might write a =head2 item for a group of get/setters. It is also Perl itself friendly. I mean, since we 'use subs @{$self->{_autoload_methods}};', Perl regards them 'virtual' subs as real ones.
My $0.0000002 worth.
Please do correct me or my code. Thanks.
Juguang.
More information about the Bioperl-l
mailing list