[Bioperl-l] return type of $feature->seq() (comments on a commit [bioperl/bioperl-live fcd90e0])

Chris Fields cjfields at illinois.edu
Tue Jun 1 17:38:46 UTC 2010


On Jun 1, 2010, at 8:42 AM, Adam Sjøgren wrote:

> Ok, so coming back to the reason for the changes in my fork¹.
> 
> It has been a while (the test in the application I am working on is from
> August 2007, so I have been using/carrying the patch for three years²),
> so I have to dig a little before it comes back to me.
> 
> Basically, I would like to make a class that inherits from
> Bio::Seq::RichSeq and extends it. When I call ->seq on features on my
> modules, I'd like to get an object of my own type back.
> 
> That sounds a little convoluted, so let me illustrate my thinking with a
> self-contained script you can run:
> 
> = = =
> #!/usr/bin/perl
> 
> use strict;
> use warnings;
> 
> use Bio::SeqFeature::Generic;
> 
> my $seq=MySeq->new(-seq=>'actg');
> $seq->extra_method;
> print "len: " . length($seq->seq) . "\n";
> 
> my $new_feature=Bio::SeqFeature::Generic->new(-primary=>'source', -start=>2, -end=>3, -strand=>1);
> $new_feature->add_tag_value(note=>'test');
> $seq->add_SeqFeature($new_feature);
> 
> foreach my $feature ($seq->get_SeqFeatures) {
>    my $obj=$feature->seq;
>    print ref($obj) . "len: " . length($obj->seq);
>    print $obj->can('extra_method') ? " OK\n" : " FAIL\n";
>    $obj->extra_method;
> }
> 
> exit 0;
> 
> package MySeq;
> 
> use base qw(Bio::Seq::RichSeq);
> 
> sub extra_accessor {
>    # ...
> }
> 
> sub extra_method {
>    # ...
>    print "extra_method called\n";
> }
> 
> # ...
> 
> 1;
> = = =
> 
> The output I expect (what my changes give rise to) is:
> 
>  extra_method called
>  len: 4
>  MySeqlen: 2 OK
>  extra_method called
> 
> But the output I get is:
> 
>  extra_method called
>  len: 4
>  Bio::PrimarySeqlen: 2 FAIL
>  Can't locate object method "extra_method" via package "Bio::PrimarySeq" at ./seq_inh_test.pl line 21.
> 
> That is what the changes on my fork try to address.
> 
> If there is a better way to accomplish the same result, I'd be flowing
> over with joy :-)
> 
> 
>  Best regards,
> 
>    Adam
> 
> 
> ¹ http://github.com/adsj/bioperl-live - this commit in particular:
>   - http://github.com/adsj/bioperl-live/commit/24ec961b217084e248f4fdbd174aadace1a27ac4
> 
> ² There actually was a little discussion about this, way back, on this
>  list:
> 
>   * Thread start, Oct 2006:
>      - http://article.gmane.org/gmane.comp.lang.perl.bio.general/13224
>   * Patch as per suggestions from Hilmar Lapp, Nov 2006:
>      - http://article.gmane.org/gmane.comp.lang.perl.bio.general/13349
> 
> -- 
>                                                          Adam Sjøgren
>                                                    adsj at novozymes.com


This is where some of the confusion lies: Bio::Seq is both a Bio::SeqI and a Bio::PrimarySeqI.  This inheritance just indicates Bio::Seq fulfills both interface methods, but note that the way this is done (regarding PrimarySeqI) is the methods delegate to a PrimarySeqI (normally a simple Bio::PrimarySeq) contained within Bio::Seq.  

A Bio::Seq's contained SeqFeatures are attached to this, not to the Bio::Seq itself, for a very good reason: no circular references (so no need for Scalar::Util::weaken).  

If you are subclassing MySeq from Bio::Seq (or RichSeq in this case), maybe the way to go is to subclass a similar MyPrimarySeq class that does what you need, bless any data from the MySeq constructor into the new MyPrimarySeq, then add methods that delegate to that within MySeq.  Does that make sense?

chris



More information about the Bioperl-l mailing list