[Bioperl-l] Auto-method caller proposal
Nathan (Nat) Goodman
natg at shore.net
Tue Jan 9 09:54:49 EST 2007
>> On Jan 3, 2007, at 1:09 PM, Sendu Bala wrote:
>>> I propose a method that sets method values based on user-supplied
>>> args to new()...
>> You might take a look at Class::AutoClass and its companion
>> Class::AutoClass::Args (both available in CPAN) which do most of what
>> you want.
> My concern is that Bio::Graph::SimpleGraph doesn't inherit from
> Bio::Root::Root. How difficult would that have been?
Inheriting from Bio::Root::Root should work fine. The code handles
multiple inheritance properly. It is also designed to co-exist with
non-AutoClass base classes (by which I mean super-classes that don't
inherit from AutoClass), such that the auto-initialization stuff is
only attempted for classes that inherit from AutoClass,
> I'm also
> concerned that it would be too difficult to change things over to
> using Class::AutoClass if _init_self() methods have to be added all
> over the place.
_init_self is only needed for classes that (1) inherit from AutoClass
and (2) that need to do non-standard initialization. See design notes,
> Alternatively, would the system work if only Bio::Root::RootI was
> based on Class::AutoClass? What would the necessary code be for
> changes in RootI and then changes in an existing run-wrapper for
Yes, it should work for Bio::Root::RootI to inherit from AutoClass.
This, however, would impose AutoClass on every BioPerl-er whether they
want it or not :)
1) The reason we do the _init_self thing, rather than doing this via
'new', is to reduce the opportunities for programmers to mess up the
auto-initialization. For auto-initialization to work as expected,
__every__ class has to do it. So, if you let programmers mess with
'new', you have to be confident that they will insert the call to
'auto_init' or whatever at the top of their code.
2) Another concern is multiple inheritance. Out of the box, Perl does
not do initialization correctly in the presence of multiple
inheritance. AutoClass::new does it correctly using a method
explained in Paul Fenwick's tutorial on object-oriented Perl. Again,
if you let programmers mess with 'new', you run the risk of them
neglecting this detail. We find that mutliple inheritance is common
in modules that are 'grafted' onto class hierarchies like BioPerl --
eg, to add application specific behavior to BioPerl classes.
This said, it would be easy to refine the AutoClass design to let
programmers contol the operation of 'new'. We'd be happy to do this or
assist others in doing this if folks want to go in this direction.
> Personally I'm in favour of not having auto-generated methods except
> as a last resort, but that last resort does need to be there or it
> becomes simply too depressing to write run-wrappers.
As I said, we use AutoClass extensively. Once you get used to
auto-generated methods, it's hard to go back!
> I'm not sure I like the idea of purely 'magic' argument processing,
> preferring an explicit method call which makes it clear what you have
> chosen to do. But perhaps that could be implemented in a RootI method
> using Class::AutoClass? If so, can you offer some example code of how
> that might be done?
Argument parsing is handled by the companion module
Class::AutoClass::Args. Here's an example of what you want. Assume
that $self is the object being intialized, @_ is the parameter list,
and you run to run the set methods for 'attributes' name, sex, and
my $args=new Class::AutoClass::Args(@_);
$self->set_attributes([qw(name sex hobbies)],$args);
Easy! But I remind you this only handles one level of initialization.
If you want to handle inheritance, and esp. multiple inheritance
correctly, more code is needed. Also note that this approach requires
that every new attribute be manually added to the initialization code
which is easy to forget.
If this is what you want, the relevant pieces could be pulled out of
AutoClass and Args and added to Bio::Root::RootI with little trouble.
More information about the Bioperl-l