I’m having trouble figuring out how to structure Perl modules in an object oriented way so I can have one parent module with a number of submodules and only the specific submodules that are needed would be loaded by a calling script. For example I want to be able to make method calls like so:
use Example::API;
my $api = Example::API->new();
my $user = {};
$user->{'id'} = '12345';
$api->Authenticate();
$user->{'info'} = $api->Users->Get($user->{'id'});
$user->{'friends'} = $api->Friends->Get($user->{'id'});
In terms of file structure I’d like to have the modules setup as follows or in whatever structure is required to make everything work correctly:
api.pm
users.pm
friends.pm
...
The reason I want to do this in the first place is so that if someone just wants to authenticate against the API they don’t have to load all the other modules. Similarly, if someone just wants to get a user’s information, they wouldn’t have to load the friends.pm module, just the users.pm. I’d appreciate it if you could provide the necessary example Perl code for setting up each module as well as explain how the file structure should be setup. If I’m going about this all wrong to accomplish what I’m try to accomplish I’d appreciate an explanation of the best way to do this and some example code on how it should be setup.
From your example, in your main module I assume you will be providing accessor methods to get at the subclasses. So all you have to do is include
require Sub::Module;at the top of that method. Nothing will happen at compile time, but the first time that code is run, perl will load the module. After the first load, the linerequire Sub::Module;will become a no-op.If all of your code is object oriented, you won’t need to worry about importing functions. But if you do, the statement
use Module qw(a b c);is interpreted as:BEGINmakes it happen at compile time, but there is nothing stopping you from using the internals at run time. Any subroutines you import at runtime must be called with parenthesis, and prototypes will not work, so unless you know what you are doing, runtime imports are probably a bad idea. Runtimerequires and access via package methods are completely safe though.So your
$api->Usersmethod might work something like this:In my examples above, I showed two translations between package names and the files they were in. In general, all
::are changed to/and.pmis added to the end. Then perl will search for that file in all of the directories in the global variable@INC. You can look at the documentation for require for all of the details.Update:
One way to cache this method would be to replace it at runtime with a function that simply returns the value: