2010-08-19 2 views
4

J'ai une structure de données assez complexe que j'ai implémentée en Perl. Cela a été divisé en environ 20 classes. Fondamentalement, chaque fois que vous voulez utiliser l'une de ces classes, vous devez les utiliser toutes.Comment puis-je créer un module qui importe de nombreux modules pour l'utilisateur?

En ce moment, si quelqu'un veut utiliser cette structure de données, ils ont besoin de faire quelque chose comme:

use Component::Root; 
use Component::Foo; 
use Component::Bar; 
use Component::Baz; 
use Component::Flib; 
use Component::Zen; 
use Component::Zen::Foo; 
use Component::Zen::Bar; 
use Component::Zen::Baz; 
... # 15 more of these... 
use Component::Last; 

pour être en mesure de manipuler toutes les parties de celui-ci. Comment puis-je écrire un module qui fait cela pour l'utilisateur, tout ce qu'ils ont à faire est

use Component; 

pour obtenir tous les autres modules importés?

Dans ce cas particulier, les modules sont toutes classes et n'ont pas d'exportation.

+0

en double: [? Comment puis-je organiser de nombreux modules Perl] (http://stackoverflow.com/questions/2788670/how-should-i-organize-many-perl-modules) – Zaid

Répondre

6

Si ce ne sont que des classes (à savoir qu'ils n'exportent toutes les fonctions ou variables lorsque vous use les), alors tout ce qui compte est qu'ils ont été chargés.

Il suffit de créer Component.pm:

package Component; 

our $VERSION = '1.00'; 

use Component::Root; 
use Component::Foo; 
use Component::Bar; 
use Component::Baz; 
use Component::Flib; 
use Component::Zen; 
use Component::Zen::Foo; 
use Component::Zen::Bar; 
use Component::Zen::Baz; 
... # 15 more of these... 
use Component::Last; 

1; # Package return value 

Vous n'avez pas besoin Exporter ou quelque chose comme ça. Cependant, au lieu d'avoir un module qui n'est rien d'autre que use instructions, il est probablement plus logique de placer ces instructions use dans la classe du nœud racine ou dans le module qui crée la structure de données.À savoir, les gens veulent dire:

use Component::Root; 
my $root = Component::Root->new(...); 

ou

use Component qw(build_structure); 
my $root = build_structure(...); 

selon la façon dont votre structure de données est normalement créée. Il est peut-être un peu déroutant pour les gens à écrire:

use Component; 
my $root = Component::Root->new(...); 

mais cela dépend vraiment de ce que votre API ressemble. S'il y a un certain nombre de classes que les gens appellent new, alors use Component pourrait être le chemin à parcourir.

+0

Votre deuxième pensée est exactement la bonne: les utilisateurs vont créer de nouvelles instances de la plupart des objets Component :: * à un moment ou un autre, au moins, initialement ou s'ils veulent faire les choses à la main. –

+0

Votre deuxième pensée est importante pour créer de bons objets. En incluant tous les modules de support requis dans le nœud racine de l'objet, l'objet est autonome. C'est une partie importante de l'encapsulation. Si je dois invoquer deux modules, l'un avec un nouveau module et l'autre pour introduire toutes mes références, alors l'objet n'est pas autonome. – HerbN

+0

'1)' Je ne peux pas croire que c'était une vraie question. Je suis tenté de penser que cela a été créé juste pour des points. - Bien sûr, vous venez de tout emballer ensemble. - '2)' En ce qui concerne la seconde, cela dépend du nombre de classes qui pourraient avoir besoin de charger ceci, si c'est juste une, chargez-les toutes dans la classe de base. Si c'est plus d'un qui doit utiliser ceci, alors empaquetez-les tous dans un module et appelez ce module de chacun des autres paquets. – vol7ron

0

Moose::Exporter semble le faire, bien que tous vos autres modules devront également l'utiliser.

En Component:

Moose::Exporter->setup_import_methods(
    also => [qw/Component::Root Component::..*/], 
); 
1
  • Vous pouvez utiliser la méthode export_to_level pour tous les paquets qui sont Exporter s.

    MyPackage->export_to_level($where_to_export, $package, @what_to_export); 
    
  • Vous pouvez également exporter tous les symboles que vous importez.

    use PackageA qw<Huey Dewey Louie>; 
    ... 
    our @ISA = qw<Exporter>; #inherit Exporter 
    our @EXPORT = qw<Huey Dewey Louie>; 
    
  • Cependant, si vous ne voulez pas exporter tous les symboles, et que vous voulez juste de charger des modules, puis il suffit d'inclure ces use déclarations ci-dessus, et un paquet dans le processus sera en mesure de les instancier en tant que classes, dites si elles étaient toutes des modules OO.

    Si elles ont été chargées avec succès, elles existeront dans %INC et dans la table des mnémoniques.

+0

Ce sont de bonnes idées si vous devez exporter quelque chose, mais dans ce cas, il n'y a rien à exporter. – cjm

0

Si les modules exportent quoi que ce soit et ne pas pas une méthode d'importation (mêmes exigences que la réponse de CJM) il vous suffit de charger les modules sans importation:

package Component; 

our $VERSION = '1.00'; 

require Component::Root; 
require Component::Foo; 
require Component::Bar; 
require Component::Baz; 
require Component::Flib; 
require Component::Zen; 
require Component::Zen::Foo; 
require Component::Zen::Bar; 
require Component::Zen::Baz; 
... # 15 more of these... 
require Component::Last; 

1; # Package return value 

Les utilisateurs du module contenterai ne:

require Component; 

Si toutefois certains modules font les exportations, vous devrez appeler leur méthode import. Vous avez donc ajouter une méthode import dans votre module Component qui les appellera:

sub import 
{ 
    Component::Root->import; 
    Component::Foo->import; 
    ... 
} 

et ainsi les utilisateurs du module devront use il:

use Component; 

Notez que vous pouvez avoir à utiliser une autre astuces si le module importé doit insérer des symboles dans le contexte de l'importateur. Voyez par exemple comment le POE's import le fait.

0

Le module Modern::Perl sauvette « enable toutes les fonctionnalités de Perl moderne avec une seule commande, » où cette commande est

use Modern::Perl; 

et ces caractéristiques sont

Pour l'instant, cela ne active les pragmas strict et warnings, ainsi que toutes les fonctionnalités disponibles dans Perl 5.10. Il active également l'ordre de résolution de la méthode C3; voir perldoc mro pour une explication.

C'est beaucoup pour une ligne de code, qui, selon le perlmod documentation est exactement équivalente à

BEGIN { require Module; import Module; } 

Tenir compte Moderne :: Perl implementation:

package Modern::Perl; 

our $VERSION = '1.03'; 

use 5.010_000; 

use strict; 
use warnings; 

use mro (); 
use feature(); 

sub import { 
    warnings->import(); 
    strict->import(); 
    feature->import(':5.10'); 
    mro::set_mro(scalar caller(), 'c3'); 
} 

1; # End of Modern::Perl 

Pour adapter cela à votre situation, à partir de votre module de niveau supérieur use tous les autres modules que vous souhaitez charger, et appeler leurs importations, le cas échéant, de MyTopLevelModule::import.

Notez que vous ne devez pas nécessairement copier

use 5.010_000; 

dans MyTopLevelModule.pm, mais ce serait une bonne idée!Selon le use documentation:

Dans la forme use VERSION particulière, VERSION peut être soit une fraction décimale positive telle que 5.006, qui sera comparée à $], ou v-chaîne de la forme v5.6.1, qui sera être comparé à $^V (aka $PERL_VERSION). Une exception est levée si VERSION est supérieure à la version de l'interpréteur Perl actuel; Perl n'essaiera pas d'analyser le reste du fichier. Comparez avec require, qui peut faire une vérification similaire au moment de l'exécution.

Questions connexes