2010-04-20 13 views
2

J'ai une classe de base comme celui-ci:Comment puis-je partager des variables entre une classe de base et une sous-classe en Perl?

package MyClass; 

use vars qw/$ME list of vars/; 
use Exporter; 
@ISA = qw/Exporter/; 
@EXPORT_OK = qw/ many variables & functions/; 
%EXPORT_TAGS = (all => \@EXPORT_OK); 

sub my_method { 

} 
sub other_methods etc { 

} 

--- more code--- 

Je veux sous-classe MyClass, mais seulement pour une méthode.

package MySubclass; 

use MyClass; 
use vars qw/@ISA/; 
@ISA = 'MyClass'; 

sub my_method { 

--- new method 

} 

Et je veux appeler cette MySubclass comme je le ferais le MyClass original, et ont encore accès à toutes les variables et les fonctions de Exporter. Cependant, j'ai des problèmes pour obtenir les variables Exporter de la classe d'origine, MyClass, pour exporter correctement. Dois-je exécuter à nouveau Exporter à l'intérieur de la sous-classe? Cela semble redondant et peu clair.

fichier Exemple:

#!/usr/bin/perl 

use MySubclass qw/$ME/; 

-- rest of code 

Mais je reçois des erreurs de compilation lorsque je tente d'importer la variable $ME. Aucune suggestion?

+0

Toujours inclure le message d'erreur que vous obtenez. –

+0

Eh bien dans ce cas particulier, je reçois juste une erreur interne du serveur lorsque j'essaie d'utiliser "MySubclass qw/$ ME /;" même quand il est dans un eval: "eval {use MySubclass qw/$ ME /;};", cependant si je dis juste "eval {use MySubclass;};" tout est trouver et dandy – Jonathan

+8

Données de classe + héritage = recette pour le brisement majeur, majeur sur la route. – hobbs

Répondre

3

Vous n'êtes pas héritant effectivement MySubclass de MyClass du tout - MySubClass est un utilisateur deMyClass. Qu'est-ce que vous faites est de contourner un peu de comportement de MyClass, mais vous ne vous tromperez si vous pensez à cela comme héritage, parce que ce n'est pas (par exemple: où est votre constructeur?) Je ne pouvais pas comprendre ce que vous avez essayé de faire jusqu'à ce que j'ai ignoré tout le code faisant et lisez simplement votre description de ce que vous voulez avoir.

D'accord, vous avez une classe qui importe des symboles - certaines fonctions et certaines variables:

package MyClass; 
use strict; 
use warnings; 

use Exporter 'import'; # gives you Exporter's import() method directly 
our @EXPORT_OK = qw/ many variables & functions/; 
our %EXPORT_TAGS = (all => \@EXPORT_OK); 
our ($ME, $list, $of, $vars); 

sub my_func { 

} 
sub other_func { 

} 
1; 

puis vous venir et d'écrire une classe qui importe tout de MyClass, l'importe tout revenir en arrière, mais remplace une fonction par une autre:

package MyBetterclass; 
use strict; 
use warnings; 
use Exporter 'import'; # gives you Exporter's import() method directly 
our @EXPORT_OK = qw/ many variables & functions /; 
our %EXPORT_TAGS = (all => \@EXPORT_OK); 
use MyClass ':all'; 

sub my_func { 
    # new definition 
} 
1; 

C'est tout! Notez que j'ai activé la vérification stricte et les avertissements, et changé les noms des "méthodes" qui sont réellement des fonctions. En outre, je n'ai pas utilisé use vars (le documentation dit qu'il est obsolète, donc c'est un gros drapeau rouge si vous voulez toujours l'utiliser sans comprendre sa mécanique).

+1

Le code que vous avez tapé imprime beaucoup de messages d'erreur et meurt: $ ./ether-test.pl Le symbole global "@EXPORT_OK" nécessite un nom de package explicite sur EtherBetterClass.pm ligne 5. Symbole global " % EXPORT_TAGS "nécessite un nom de package explicite sur EtherBetterClass.pm ligne 6. Le symbole global" @EXPORT_OK "nécessite un nom de package explicite sur EtherBetterClass.pm ligne 6. BEGIN non sécurisé après erreurs - compilation annulée à la ligne EtherBetterClass.pm 7. BEGIN a échoué - compilation annulée à la ligne ./ether-test.pl 4. –

+0

BTW qui n'est pas mon downvote. –

+1

Donc, basiquement, la réponse est que je dois importer toutes mes variables, puis exporter ensuite à l'aide de l'exportateur. Il n'y a évidemment aucun moyen de le faire automatiquement? Droite? J'utilise "use vars" au lieu de "our" car je prévois de distribuer mon script à des personnes qui utilisent ou non la dernière version de perl 5. – Jonathan

8

Vous devriez accéder à tout par des méthodes. Oubliez de passer des variables autour.

Vous obtenez une erreur de syntaxe parce que vous avez une erreur de syntaxe:

use MySubclass /$ME/; # syntax error - that's the match operator 

Vous voulez une liste il y a:

use MySubclass qw/$ME/; 

Cependant, ne pas le faire. Fournir l'accès à ces données par des méthodes. Puisque vous héritez les méthodes, vous n'avez pas besoin (et ne doit pas utiliser) Exportateur:

package MyClass; 

BEGIN { 
my $ME; 
sub get_me { $ME } 
sub set_me { $ME = shift } 
} 

Maintenant, votre sous-classe est juste:

package MySubclass; 
use parent(MyClass); 
sub my_method { ... } 

Il existe différents modules qui peuvent automatiquement gérer les détails de l'accesseur pour vous si vous avez plusieurs variables à partager.

+0

J'ai juste oublié d'inclure le "qw" quand j'ai écrit mon exemple. Je réalise que je peux exporter n'importe quelle variable par une méthode, mais j'espère qu'il y aurait un moyen d'exporter TOUTES mes variables sans créer une méthode pour chacune d'entre elles. Si j'appelle "use MyClass qw /: all /;" Je peux accéder à TOUTES mes variables. Je veux que ça fonctionne de la même façon mais avec "use MySubclass qw /: all /;" – Jonathan

+4

Eh bien, revenir en arrière et résoudre votre question alors. Ne tapez pas de nouveau code. Montrez-nous le vrai code. –

+1

Le code réel est un moyen compliqué et fastidieux à poster. J'ai seulement posté ce qui est nécessaire à ma question. – Jonathan

4

En général, OO Perl et Exportateur sont normalement maintenus séparés au lieu de les mélanger ensemble. Ceci est une des raisons. Comme brian l'a dit, vous aurez beaucoup plus de facilité à le faire fonctionner et à le prolonger dans le futur si vous prenez toutes les conneries que vous exportez, transformez-le en propriétés/méthodes de classe , et se débarrasser complètement de l'exportateur. Le simple fait que la façon dont vous voulez le faire vous oblige à importer et à réexporter tout ce qui devrait être un grand indice, qu'il y a probablement une meilleure façon de le faire (c'est-à-dire d'une manière qui n'implique pas Exporter).

+0

Je réalise que ce n'est pas la meilleure idée et je prévois de trouver une autre méthode. J'ai cependant supposé que Perl exporte automatiquement les variables lors de l'utilisation de la POO, mais je commence à comprendre pourquoi c'est une mauvaise idée. Je vais trouver un autre moyen, mais au moins pour l'instant je sais comment je pourrais le faire (importer que réexporter), mais seulement si c'est absolument nécessaire. – Jonathan

0
 # use setters and getters the Perl's way 
     # 
     # --------------------------------------- 
     # return a field's value 
     # --------------------------------------- 
     sub get { 

      my $self = shift; 
      my $name = shift; 
      return $self->{ $name }; 
     } #eof sub get 


     # 
     # --------------------------------------- 
     # set a field's value 
     # --------------------------------------- 
     sub set { 

      my $self = shift; 
      my $name = shift; 
      my $value = shift; 
      $self->{ $name } = $value; 
     } 
     #eof sub set 


     # 
     # --------------------------------------- 
     # return the fields of this obj instance 
     # --------------------------------------- 
     sub dumpFields { 
      my $self = shift; 

      my $strFields =(); 
      foreach my $key (keys %$self) { 
       $strFields .= "$key = $self->{$key}\n"; 
      } 

      return $strFields; 
     } #eof sub dumpFields