[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