Joel Berger
Joel Berger

Reputation: 20280

Instantiate a module from variable contents

I feel like this might be a silly question or possibly even one of those unexpectedly inflammatory ones; still I am curious.

I have a configuration file I read in, and then based on the contents create objects of different types. A good model would be a library catalog. Lets say I have packages (classes) Books::Historical, Books::SciFi, Books::Romance, etc. And the config has hashes like

%book = (
  type => 'SciFi',
  name => 'Journey to the Center of the Earth',
  ...
);

As I read the conf file I want to create objects of these types. I know I could do something like:

my $book_obj;
if ($book{'type'} eq 'SciFi') {
  $book_obj = Books::SciFi->new();
  #do stuff with $book_obj
} elsif ($book{'type'} eq 'Romance') { ...

but I was wondering if there is some way to do something more like

my $book_obj = Books::$book{'type'}->new();

so that I don't need to setup a huge if tree?

PS. yes, I will probably contain this functionality inside the Books package, that is to say not exposed, but I will need to deal with this eventually any way I do it.

Upvotes: 3

Views: 472

Answers (1)

friedo
friedo

Reputation: 66937

Just construct the classname by putting it in a scalar, then instantiate:

my $classname = 'Books::' . $book{type};
my $book_obj = $classname->new;

Remember that the LHS of the -> operator can be pretty much anything that evaluates to an object or classname.

So you could also do something like this:

my $book_obj = ${ \"Books::$book{type}" }->new;

but that's pretty ugly.

Upvotes: 4

Related Questions