2017-09-08 3 views
1

Je suis nouveau à Perl Moose, et j'essaie d'accomplir cette tâche simple. J'ai ma classe Moose « TestObject » définis:Moose: Array of Objects-> loop through Attribut

package TestObject; 
use Moose; 
use namespace::autoclean; 

has 'Identifier' => (is =>'ro',isa=>'Str'); 

around BUILDARGS => sub 
{ 
    my $orig = shift; 
    my $class = shift; 

    if (@_ == 1 && ! ref $_[0]) { 
     return $class->$orig(Identifier => $_[0]); 
    } 
    else { 
     return $class->$orig(@_); 
    } 
}; 
__PACKAGE__->meta->make_immutable; 
1; 

Dans un autre script que je suis en train d'accéder à l'attribut « Identifier » directement à partir d'un tableau de « TestObjects »:

use TestObject; 
use experimental 'smartmatch'; 
my @aArray1=(TestObject->new("z003"),TestObject->new("t302"),TestObject->new("r002")); 
my $sIdent="t302"; 
if([email protected]>Identifier) 
{ 
    print "Element with Identifier".$sIdent." found."; 
} 

Ce n » t travail. Je pourrais mettre en œuvre une solution de contournement comme ceci:

my @aIdent=(); 
foreach my $sObject(@aArray1) 
{ 
    push(@aIdent,$sObject->Identifier); 
} 
if([email protected]) 
{ 
    print "Element with Identifier".$sIdent." found."; 
} 

mais cela ne semble pas être la solution la plus élégante. Quelle est la solution la plus élégante pour résoudre ce problème?

+4

Ne nommez pas votre classe _Object_. C'est vraiment déroutant! – simbabque

+3

Je dirais que je n'utilise pas l'opérateur smartmatch. C'est expérimental et peut changer ou être rejeté finalement à un moment donné. – simbabque

Répondre

4

Ne faites pas cela avec l'opérateur smartmatch. C'est expérimental pour une raison, et il pourrait être retiré des futures versions de Perl, ou changer la façon dont cela fonctionne, comme c'est déjà fait.

Au lieu de cela, cela peut être réalisé avec un simple grep.

my @aArray1 = ( 
    TestObject->new("z003"), 
    TestObject->new("t302"), 
    TestObject->new("r002"), 
); 

my $sIdent = "t302"; 
if (grep { $_->Identifier eq $sIdent } @aArray1) { 
    print "Element with Identifier" . $sIdent . " found."; 
} 

Si vous voulez que, pour être un peu plus courte, vous pouvez également utiliser first from List::Util. C'est un peu plus rapide car cela arrêtera de s'occuper du premier match.

use List::Util 'first'; 
my @aArray1 = ( 
    TestObject->new("z003"), 
    TestObject->new("t302"), 
    TestObject->new("r002"), 
); 

my $sIdent = "t302"; 
if (first { $_->Identifier eq $sIdent } @aArray1) { 
    print "Element with Identifier" . $sIdent . " found."; 
} 

Quelques mots de conseils sur votre code:

  • Ne pas nommer jamais quoi que ce soit de classe avec objet. Cela va vous embrouiller, futur vous et le gars de la maintenance. Si vous ne comprenez pas la différence entre classe et objet, lire à ce sujet s'il vous plaît.
  • Les noms de variables et les fonctions en Perl sont toujours écrits en minuscules par convention, et nous utilisons snake case. Camel case est réservé pour les noms de paquets.
+2

"Ne nomme jamais une classe avec un objet." L'un de mes premiers travaux consistait à travailler sur le composant de génération de base de données d'un outil de modélisation de données. Notre base de données avait des tables appelées "base de données", "table" et "colonne". C'était ** très ** déroutant! –

+0

@simbabque: Thx pour votre réponse. Oui, je connais la différence entre la classe et l'objet, juste écrit cet extrait de code pour poster sur stackoverflow. Pourriez-vous m'aider avec un problème similaire? J'ai du mal à implémenter la syntaxe grep dans un objet List :: Compare: my $ lc = Liste :: Compare-> new ('-u', \ @ aIdentList, \ @ {(grep {$ _-> Identifier} @ aArray1)}); – airborne

+1

@airborne il suffit de poser une nouvelle question pour cela s'il vous plaît. – simbabque