Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Runtime loading of arbitrary objects

by Anonymous Monk
on Aug 21, 2000 at 13:29 UTC ( [id://28784]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

My problem is: how do I instantiate an object dynamically
runtime, when I only know the name of its class?

Eg. something like:
my $calvin = SomeFunkyLoader("Calvin::Hobbes"); # invokes Calvin::Hobbes->new

The only thing about the objects, the class name, will be provided run-time only.

How do I do this??

Replies are listed 'Best First'.
RE: Runtime loading of arbitrary objects
by davorg (Chancellor) on Aug 21, 2000 at 14:12 UTC

    If I understand you correctly, this does what you want.

    use strict; my $type = shift || 'CGI'; require "$type.pm"; my $obj = $type->new; print ref $type;

    The trick is to use require instead of use, as require is executed at runtime (when you will know which object you want) as opposed to use which is executed at compile time (when you won't know what you want).

    This will work as long as you're using pure OO modules which don't export anything that you need. If you need to use exported data then you'll have to add a call to:

    $type->import;

    After the call to require.

    --
    <http://www.dave.org.uk>

    European Perl Conference - Sept 22/24 2000, ICA, London
    <http://www.yapc.org/Europe/>
RE: Runtime loading of arbitrary objects
by merlyn (Sage) on Aug 21, 2000 at 17:26 UTC
    Well, taking your question literally, it's simply:
    $class_name = "Calvin::Hobbes"; # from some value above my $new_object = $class_name->new;
    There's no magic involved in using a string as a classname.

    But perhaps you also intend to dynamically load a require file. In which case, I'd do something like this:

    if (grep $class_name eq $_, qw(Calvin::Hobbes Peter::Gabriel Dog::Day: +:Afternoon)) { # must validate the name, or security holes will run rampant eval "require $class_name"; die $@ if $@; $object = $class_name->new; }
    Notice the validation there. Essential. Without that, damage will result. Use whatever mechanism you want, but it must match one of the names you are expecting, and certainly not one of the names you are not.

    Also, this approach presumes a constant constructor called new. That's not necessarily the case, since Perl doesn't require any constructor called new to be defined. In that case, you'll want a table, like:

    my %make_a = qw( Calvin::Hobbes new Peter::Gabriel play Dog::Day::Afternoon watch ); ... if (my $constructor = $make_a{$class_name}) { unless ($INC{$class_name}) { eval "require $class_name"; die $@ if $@; } $object = $class_name->$constructor(); }
    The nice thing about this approach is that the table of "how" is automatically the validation table for "permitted".

    -- Randal L. Schwartz, Perl hacker

Re: Runtime loading of arbitrary objects
by matthew (Acolyte) on Aug 21, 2000 at 17:48 UTC
    -or- I've got a sytem that uses a Session module to define and control all the business rules of any given application. It uses a object factory method:
    ########################################### # object factory method # $class is the class of the method to be created sub new_object { my $self = shift; my $class = shift; my $id = shift; my $dbh = $self->{'dbh'}; my $object = { 'id' => $id, 'dbh' => $dbh, }; bless $object, $class; $object->init; return $object; }

    $class is the object class, $id is an optional object id (for instatiating a particular object from a database for example). The method then calls $class->init which is an initialization method which handles all the details of the given class. Essentially it's just a generic constructor. Technically your classes don't need one if they are going to be called by the base module.

    You have to use all the modules you plan to invoke this way in the base "Session" module, but you already know all the modules you're going to use, right?

    -Matthew

Re: Runtime loading of arbitrary objects
by JanneVee (Friar) on Aug 21, 2000 at 13:41 UTC
    You could always try to run it trough an eval statement.

    Build an expression to run through eval and catch errors if it was succefull or not...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://28784]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (7)
As of 2024-04-19 13:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found