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

I'm still new to object oriented perl and am having a very difficult time with one thing.

I have a main script and then I have a number of packages. Each package has a class and some methods.

At least two of these classes will be used by many (if not all) of the other packages. These two are called:
Creates an object containing all system config settings
Creates an object containing all the session/login info about the currently logged-in user.

The problem is that specific instances of both objects need to be accessed by multiple (if not all) other packages. That is, I don't want to do a 'use Login; use Config;' inside of *every* package that needs the config or login data.

If I have the following packages, I want them ALL to access the same instance of the login or config object, instead of each having it's own copy/instance - including the main script itself.

I'm not sure how to do this?

I've been looking through the Perl Cookbook as well as Merlyn's newer Object/References book and if they contain the answers to this, I didn't know it when I saw it.

Is my only solution to do one of the following or is there something more elegant?

1) Create an instance of the config and login objects in the main script. Then when I access any other packages or classes from the main script, have the first arguement (after the class/$self) be a reference to $Main::login so that each package could then be accessing the main instance of it? Such as $main::login->{_login}->{session_id}. And if I access a class from another class that itself is accessed from the main scripted (say, accesses and accesses, I would have pass to a reference to the reference of $Main::login or $Main::config . . .?


2) Something to do with prototyping?

Needless to say, I'm a bit lost right now. I've spent a few days trying to figure this one out and my little project is at an impasse until I do something (since, obviously, config and login objects are a bit essential!).
  • Comment on Creating 'universal' instances of objects?

Replies are listed 'Best First'.
Re: Creating 'universal' instances of objects?
by smalhotra (Scribe) on Aug 04, 2003 at 13:57 UTC
    A couple of points:
    1. The "universal" object you are trying to create is called a "singleton" (correct me if I'm wrong). Search PM or google for more information. Or look at singleton.
    2. Although 'use'ing the modules specifically makes it easier for you and anyone else who looks at your code to see what's coming from where you might try to use one package to handle all these for you. Example:
    package MyApp; use Config; use Login; sub config { return $config_object } sub login { return $login_object } ## main script use MyApp; MyApp->config->do_something(); ## or my $config = MyApp->config(); $config->{do_something}
    I hope this gives you an idea.

    $will->code for @food or $$;

Re: Creating 'universal' instances of objects?
by Abigail-II (Bishop) on Aug 04, 2003 at 13:52 UTC
    So, why do you use objects in the first place? If you just want to have one instance of each class anyway, why not just use class methods, and class variables?


      Even if current design suggests that the objects will be unique, it is still a good idea to implement such singleton classes with a single managed instance of that class. Class-oriented singleton resources would be more brittle and resistant to refactoring.

      In the future he may choose to divide global.conf into server.conf and a number of foo-module.conf, and in that case, an object-backed singleton class easily graduates as more complex structures are needed.

      [ e d @ h a l l e y . c c ]

Re: Creating 'universal' instances of objects?
by bm (Hermit) on Aug 04, 2003 at 15:27 UTC
    Sounds to me that Class::Singleton is exactly what you are after.

    Deriving from that class will ensure that only one instance of your class will be returned:

    package Grok; use vars qw(@ISA); @ISA = qw(Class::Singleton); package Main; my $one = Grok->instance(); # returns a new instance my $two = Grok->instance(); # returns same instance
    Hope this helps.
Re: Creating 'universal' instances of objects?
by jonadab (Parson) on Aug 04, 2003 at 18:32 UTC

    The singleton class idea is probably best, but here is another option: your main script could create your one instance and assign it to a global variable, which the other modules could access at will. Something like the following then would be at the top of each file:

    use Login; use Config; our ($login, $config) = (Login::new(), Config::new());

    This is in some ways less elegant than the singleton, but it leaves you the option that some modules can create their own instances if desired, but others can use the main instance.

Re: Creating 'universal' instances of objects?
by archon (Monk) on Aug 04, 2003 at 20:51 UTC