Hello tout le monde,
voilà, je commence à m'intéresser un peu à la POO en Perl, et, bien que je sache que les développeurs Perl travaillent toujours proprement, et qu'on a pas besoin de garde fous je voulais, pour ma culture personnelle, développer un peu le fonctionnement des constructeurs... et par extension, des références en Perl d'ailleurs.
En gros, l'idée est la suivante: grâce aux supers cours/FAQ de ce même site (merci encore à tous les auteurs de la FAQ et des cours que je ne nommerai pas car j'en oublierai sûrement), j'ai commencé à faire une petite classe basique. Pour le constructeur, je passe en paramètre une référence anonyme à une table de hashage contenant les attributs (j'espère avoir le bon vocabulaire =).
Pour le moment, j'avais 2 attributs :
- un scalaire
- une table de hashage dont je passe la référence
Mon "problème", c'est que je voulais pouvoir "recopier" la table de hashage pour éviter de travailler sur la version passée en paramètre. J'ai une solution en utilisant une table temporaire, mais je voulais savoir s'il n'y avait pas quelque chose de plus propre...
Exemple:
test.pl
Server.pm
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #!/usr/bin/perl use strict; use warnings; use Data::Dumper; use Server; my $cfg_ip='1.2.3.4'; my %cfg_users=( toto => 'titi' ); my $server = Server->new( { ip => $cfg_ip, ref_users => \%cfg_users } ); print $server->to_string(); print Dumper(\%cfg_users); print $cfg_ip;
Exécution
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 # --- fichier Server.pm --- package Server; use strict; use warnings; use Carp; # constructeur: # 1. nom de la classe (passe automatiquement) # 2. adresse ip du serveur # 3. tableau de hachage user => mdp sub new { my ($classe, $ref_args) = @_; # Vérification de la classe $classe = ref($classe) || $classe; # Vérification des champs nom, prenom et sexe foreach my $attribut (qw/ ip ref_users /) { croak ("[WARN] Attribut $attribut manquant") unless ( defined $ref_args->{$attribut} ); } # Création de la référence anonyme de hachage vide (futur objet) my $this = {}; # Liaison de l'objet à la classe bless ($this, $classe); $this->{_IP} = $ref_args->{ip}; $this->{_USERS} = $ref_args->{ref_users}; # test modif valeurs pour la portée $this->{_IP} = '4.3.2.1'; $this->{_USERS}->{toto} = 'tutu'; return $this; } # to_string: sub to_string { my $this = shift; print "$this->{_IP} :\n"; foreach (sort keys %{$this->{_USERS}}) { printf ("%10s\t%10s\n", $_, $this->{_USERS}->{$_}); } } 1;
Bon, on voit bien que si je modifie les valeurs dans la classe, l'adresse ip du programme test.pl n'est pas modifiée (normal, je copie la valeur), alors que la hashtable des utilisateurs est modifiée car je passe par une référence... jusque là, ok !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 D:\50-Travail>perl test.pl 4.3.2.1 : toto tutu $VAR1 = { 'toto' => 'tutu' }; 1.2.3.4
Maintenant, je souhaitais "protéger" la hashtable en entrée pour éviter ce genre de problème. Je n'ai trouvé qu'une solution, remplacer dans le constructeur ceci:
par cela:
Code : Sélectionner tout - Visualiser dans une fenêtre à part $this->{_USERS} = $ref_args->{ref_users};
Alors ça marche :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 my %tmp_users = %{$ref_args->{ref_users}}; $this->{_USERS} = \%tmp_users;
mais je trouve pas ça beau
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 D:\50-Travail>perl test.pl 4.3.2.1 : toto tutu $VAR1 = { 'toto' => 'titi' }; 1.2.3.4
Un indice ?!
Merci d'avance.
Partager