Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Plusieurs implementations d'une interface pour un module

6 réponses
Avatar
Olivier Croquette
Salut à tous

J'en suis encore à mes débuts en Perl, et j'ai le problème suivant: je
veux écrire sous forme de modules plusieurs implémentations d'une même
interface.
Le but est de décider à la compilation (par exemple en fonction d'une
variable d'environnement) de quelle implémentation utiliser.

Bref, j'ai:

main.pl
module.pm
module_imp1.pm
module_imp2.pm

main est censé faire un "use module", qui "redirigerait" vers
l'implémentation correcte.
Bien sûr, je veux éviter d'avoir à écrire quoique soit dans module.pm
(surtout pas une fonction par fonction à transférer).

J'ai essayé de faire ça à base de ISA et Exporter, mais je ne suis
arrivé à rien, et je ne suis pas sûr d'être sur la bonne piste.

Des idées peut-être?

Merci!

6 réponses

Avatar
jl_morel
Dans l'article <fq6s6p$766$01$,
a dit...

J'en suis encore à mes débuts en Perl, et j'ai le problème suivant: je
veux écrire sous forme de modules plusieurs implémentations d'une même
interface.
Le but est de décider à la compilation (par exemple en fonction d'une
variable d'environnement) de quelle implémentation utiliser.

Bref, j'ai:

main.pl
module.pm
module_imp1.pm
module_imp2.pm

main est censé faire un "use module", qui "redirigerait" vers
l'implémentation correcte.
Bien sûr, je veux éviter d'avoir à écrire quoique soit dans module.pm
(surtout pas une fonction par fonction à transférer).

J'ai essayé de faire ça à base de ISA et Exporter, mais je ne suis
arrivé à rien, et je ne suis pas sûr d'être sur la bonne piste.

Des idées peut-être?



Peut être mettre dans module.pm (si j'ai bien compris la question)

if ( CONDITION ) {
require module_imp1;
}
else {
require module_imp2;
}

Si vous avez beaucoup d'implémentations, vous pouvez même utiliser la forme
require $implémentation;
où $implémentation est obtenu par une liste, un hash...etc

Si vous avez des constantes à importer il faut les gérer vous même en
appelant la fonction import() de chaque module.

HTH

--
J-L.M.
http://www.bribes.org/perl

Avatar
ocroquette
On Feb 28, 11:38 pm, (Jean-Louis MOREL) wrote:
Peut être mettre dans module.pm (si j'ai bien compris la question)

if ( CONDITION ) {
require module_imp1;}
else {
require module_imp2;
}


OK, mais le problème est de faire en sorte que:
use module;
f();
appelle la fonction correspondante de l'implementation, et ce
automatiquement, avec le moins de code possible.

J'ai trouve une solution a base de ISA:

package module_imp1;

sub foo {
print("Inside module_imp1::foon");
}

package module;
@ISA = (module_imp1);

package main;
module->foo();


C'est exactement ce que je veux faire, néanmoins cela oblige à
utiliser une syntaxe "objet" (->) alors que je travaille sur un
programme complètement orienté fonctions. :(

Avatar
ocroquette
On Feb 29, 10:34 am, wrote:
C'est exactement ce que je veux faire, néanmoins cela oblige à
utiliser une syntaxe "objet" (->) alors que je travaille sur un
programme complètement orienté fonctions. :(


Une autre solution, basée sur AUTOLOAD et la recherche dynamique de
fonction cette fois:

package module_imp1;
use strict;

sub foo {
print("Inside module_imp1::foon");
}


package module;

sub AUTOLOAD {
our $AUTOLOAD;
no strict "refs";
my $fnname = (split(/::/,$AUTOLOAD))[-1];
my $fn = "module_imp1::" . $fnname;
if ( exists &$fn ) {
return &$fn(@_);
}
die("Error: Unknown function $AUTOLOAD @_n");
}


package main;
module::foo();


Ca correspond mieux à mon cahier des charges, mais c'est pas très
élegant :-/

Avatar
Paul Gaborit
À (at) Fri, 29 Feb 2008 01:34:04 -0800 (PST),
écrivait (wrote):
OK, mais le problème est de faire en sorte que:
use module;
f();
appelle la fonction correspondante de l'implementation, et ce
automatiquement, avec le moins de code possible.


C'est un problème d'import/export de fonctions(). Il suffit que chaque
implémentation exporte correctement les fonctions voulues (via
Exporter).

Ensuite le package 'Module' peut faire :

----------------------------------------
package Module;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK;
our @EXPORT;

BEGIN {
my $implementation;
if (defined $ENV{IMPLEMENTATION1}) {
$implementation = 'Module::Imp1';
} else {
$implementation = 'Module::Imp2';
}
warn "Choix : $implementationn";

eval "use $implementation";
@EXPORT = @{"${implementation}::EXPORT"};
@EXPORT_OK = @{"${implementation}::EXPORT_OK"};
}

1;
----------------------------------------


--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
jl_morel
Dans l'article <c0b69661-59f6-4d3c-8884-
, a dit...

On Feb 28, 11:38 pm, (Jean-Louis MOREL) wrote:
Peut être mettre dans module.pm (si j'ai bien compris la question)

if ( CONDITION ) {
require module_imp1;}
else {
require module_imp2;
}


OK, mais le problème est de faire en sorte que:
use module;
f();
appelle la fonction correspondante de l'implementation, et ce
automatiquement, avec le moins de code possible.

J'ai trouve une solution a base de ISA:

package module_imp1;

sub foo {
print("Inside module_imp1::foon");
}

package module;
@ISA = (module_imp1);

package main;
module->foo();


C'est exactement ce que je veux faire, néanmoins cela oblige à
utiliser une syntaxe "objet" (->) alors que je travaille sur un
programme complètement orienté fonctions. :(



Je verrais plutôt quelque chose comme ça :
(suivant la valeur booléenne de $imp on sélectionne l'implémentation)

package module_imp1;
use strict;
use warnings;
use Exporter;

our @ISA = qw(Exporter);
our @EXPORT = qw( foo );

sub foo {
print "Inside module_imp1::foon";
}

1;
__END__

package module_imp2;
use strict;
use warnings;
use Exporter;

our @ISA = qw(Exporter);
our @EXPORT = qw( foo );

sub foo {
print "Inside module_imp2::foon";
}

1;
__END__

package module;
use Exporter;

our @ISA = qw(Exporter);
our @EXPORT = qw( foo );

my $imp = 0; # choix implémentation

if ($imp) {
require module_imp1;
module_imp1->import();
}
else {
require module_imp2;
module_imp2->import();
}

1;
__END__

#!/usr/bin/perl
use strict;
use warnings;

use module;
foo();

__END__


HTH

--
J-L.M.
http://www.bribes.org/perl


Avatar
Olivier Croquette
Jean-Louis MOREL wrote, On 29/02/08 12:10:
if ($imp) {
require module_imp1;
module_imp1->import();
}
else {
require module_imp2;
module_imp2->import();
}


Super, c'est exactement ça que je m'imaginais.
Il me manquait juste le import. Je n'aurais pas imaginer qu'on puisse
injecter les symboles d'un paquet dans un autre aussi facilement.