Programmation orientée objet en PERL

Nous avons déjà étudié les références dans les tableaux et hachages anonymes Perl et Perl. Le concept orienté objet en Perl est très basé sur des références, des tableaux et des hachages anonymes. Commençons par apprendre les concepts de base de Perl orienté objet.

Principes de base des objets

Il existe trois termes principaux, expliqués du point de vue de la manière dont Perl gère les objets. Les termes sont objet, classe et méthode.

  • Un objectdans Perl est simplement une référence à un type de données qui sait à quelle classe il appartient. L'objet est stocké comme référence dans une variable scalaire. Étant donné qu'un scalaire ne contient qu'une référence à l'objet, le même scalaire peut contenir différents objets dans différentes classes.

  • UNE class dans Perl est un package qui contient les méthodes correspondantes requises pour créer et manipuler des objets.

  • UNE methoddans Perl est un sous-programme, défini avec le paquet. Le premier argument de la méthode est une référence d'objet ou un nom de package, selon que la méthode affecte l'objet actuel ou la classe.

Perl fournit un bless() function, qui est utilisée pour renvoyer une référence qui devient finalement un objet.

Définition d'une classe

Il est très simple de définir une classe en Perl. Une classe correspond à un package Perl dans sa forme la plus simple. Pour créer une classe en Perl, nous construisons d'abord un package.

Un package est une unité autonome de variables et de sous-programmes définis par l'utilisateur, qui peut être réutilisée encore et encore.

Les packages Perl fournissent un espace de noms séparé au sein d'un programme Perl qui empêche les sous-programmes et les variables d'être en conflit avec ceux des autres packages.

Pour déclarer une classe nommée Person en Perl, nous faisons -

package Person;

La portée de la définition de package s'étend jusqu'à la fin du fichier ou jusqu'à ce qu'un autre mot-clé de package soit rencontré.

Créer et utiliser des objets

Pour créer une instance d'une classe (un objet), nous avons besoin d'un constructeur d'objet. Ce constructeur est une méthode définie dans le package. La plupart des programmeurs choisissent de nommer cette méthode de constructeur d'objet comme nouvelle, mais en Perl, vous pouvez utiliser n'importe quel nom.

Vous pouvez utiliser n'importe quel type de variable Perl comme objet en Perl. La plupart des programmeurs Perl choisissent des références à des tableaux ou des hachages.

Créons notre constructeur pour notre classe Person en utilisant une référence de hachage Perl. Lors de la création d'un objet, vous devez fournir un constructeur, qui est un sous-programme dans un package qui renvoie une référence d'objet. La référence d'objet est créée en bénissant une référence à la classe du package. Par exemple -

package Person;
sub new {
   my $class = shift;
   my $self = {
      _firstName => shift,
      _lastName  => shift,
      _ssn       => shift,
   };
   # Print all the values just for clarification.
   print "First Name is $self->{_firstName}\n";
   print "Last Name is $self->{_lastName}\n";
   print "SSN is $self->{_ssn}\n";
   bless $self, $class;
   return $self;
}

Voyons maintenant comment créer un objet.

$object = new Person( "Mohammad", "Saleem", 23234345);

Vous pouvez utiliser un hachage simple dans votre consturctor si vous ne souhaitez attribuer aucune valeur à une variable de classe. Par exemple -

package Person;
sub new {
   my $class = shift;
   my $self = {};
   bless $self, $class;
   return $self;
}

Définition des méthodes

D'autres langages orientés objet ont le concept de sécurité des données pour empêcher un programmeur de modifier directement les données d'un objet et ils fournissent des méthodes d'accès pour modifier les données d'objet. Perl n'a pas de variables privées mais nous pouvons toujours utiliser le concept de méthodes d'assistance pour manipuler les données d'objets.

Permet de définir une méthode d'assistance pour obtenir le prénom de la personne -

sub getFirstName {
   return $self->{_firstName};
}

Une autre fonction d'aide pour définir le prénom de la personne -

sub setFirstName {
   my ( $self, $firstName ) = @_;
   $self->{_firstName} = $firstName if defined($firstName);
   return $self->{_firstName};
}

Jetons maintenant un coup d'œil à l'exemple complet: le package Keep Person et les fonctions d'assistance dans le fichier Person.pm.

#!/usr/bin/perl 

package Person;

sub new {
   my $class = shift;
   my $self = {
      _firstName => shift,
      _lastName  => shift,
      _ssn       => shift,
   };
   # Print all the values just for clarification.
   print "First Name is $self->{_firstName}\n";
   print "Last Name is $self->{_lastName}\n";
   print "SSN is $self->{_ssn}\n";
   bless $self, $class;
   return $self;
}
sub setFirstName {
   my ( $self, $firstName ) = @_;
   $self->{_firstName} = $firstName if defined($firstName);
   return $self->{_firstName};
}

sub getFirstName {
   my( $self ) = @_;
   return $self->{_firstName};
}
1;

Utilisons maintenant l'objet Person dans le fichier employee.pl comme suit -

#!/usr/bin/perl

use Person;

$object = new Person( "Mohammad", "Saleem", 23234345);
# Get first name which is set using constructor.
$firstName = $object->getFirstName();

print "Before Setting First Name is : $firstName\n";

# Now Set first name using helper function.
$object->setFirstName( "Mohd." );

# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "Before Setting First Name is : $firstName\n";

Lorsque nous exécutons le programme ci-dessus, cela produit le résultat suivant -

First Name is Mohammad
Last Name is Saleem
SSN is 23234345
Before Setting First Name is : Mohammad
Before Setting First Name is : Mohd.

Héritage

La programmation orientée objet a un concept très bon et utile appelé héritage. L'héritage signifie simplement que les propriétés et méthodes d'une classe parent seront disponibles pour les classes enfants. Vous n'avez donc pas besoin d'écrire le même code encore et encore, vous pouvez simplement hériter d'une classe parent.

Par exemple, nous pouvons avoir une classe Employee, qui hérite de Person. C'est ce qu'on appelle une relation «isa» car un employé est une personne. Perl a une variable spéciale, @ISA, pour vous aider. @ISA régit l'héritage (de méthode).

Voici les points importants à prendre en compte lors de l'utilisation de l'héritage -

  • Perl recherche dans la classe de l'objet spécifié la méthode ou l'attribut donné, c'est-à-dire la variable.

  • Perl recherche les classes définies dans le tableau @ISA de la classe d'objets.

  • Si aucune méthode n'est trouvée aux étapes 1 ou 2, alors Perl utilise un sous-programme AUTOLOAD, s'il en trouve un dans l'arborescence @ISA.

  • Si une méthode correspondante ne peut toujours pas être trouvée, Perl recherche la méthode dans la classe UNIVERSAL (package) qui fait partie de la bibliothèque Perl standard.

  • Si la méthode n'a toujours pas été trouvée, Perl abandonne et lève une exception d'exécution.

Donc, pour créer une nouvelle classe Employee qui héritera des méthodes et des attributs de notre classe Person, nous codons simplement comme suit: Conservez ce code dans Employee.pm.

#!/usr/bin/perl

package Employee;
use Person;
use strict;
our @ISA = qw(Person);    # inherits from Person

Maintenant, Employee Class a toutes les méthodes et attributs hérités de la classe Person et vous pouvez les utiliser comme suit: Utilisez le fichier main.pl pour le tester -

#!/usr/bin/perl

use Employee;

$object = new Employee( "Mohammad", "Saleem", 23234345);
# Get first name which is set using constructor.
$firstName = $object->getFirstName();

print "Before Setting First Name is : $firstName\n";

# Now Set first name using helper function.
$object->setFirstName( "Mohd." );

# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "After Setting First Name is : $firstName\n";

Lorsque nous exécutons le programme ci-dessus, cela produit le résultat suivant -

First Name is Mohammad
Last Name is Saleem
SSN is 23234345
Before Setting First Name is : Mohammad
Before Setting First Name is : Mohd.

Remplacement de méthode

La classe enfant Employee hérite de toutes les méthodes de la classe parent Person. Mais si vous souhaitez remplacer ces méthodes dans votre classe enfant, vous pouvez le faire en donnant votre propre implémentation. Vous pouvez ajouter vos fonctions supplémentaires dans la classe enfant ou vous pouvez ajouter ou modifier la fonctionnalité d'une méthode existante dans sa classe parent. Cela peut être fait comme suit: modifier le fichier Employee.pm.

#!/usr/bin/perl

package Employee;
use Person;
use strict;
our @ISA = qw(Person);    # inherits from Person

# Override constructor
sub new {
   my ($class) = @_;

   # Call the constructor of the parent class, Person.
   my $self = $class->SUPER::new( $_[1], $_[2], $_[3] );
   # Add few more attributes
   $self->{_id}   = undef;
   $self->{_title} = undef;
   bless $self, $class;
   return $self;
}

# Override helper function
sub getFirstName {
   my( $self ) = @_;
   # This is child class function.
   print "This is child class helper function\n";
   return $self->{_firstName};
}

# Add more methods
sub setLastName{
   my ( $self, $lastName ) = @_;
   $self->{_lastName} = $lastName if defined($lastName);
   return $self->{_lastName};
}

sub getLastName {
   my( $self ) = @_;
   return $self->{_lastName};
}

1;

Maintenant, essayons à nouveau d'utiliser l'objet Employee dans notre fichier main.pl et exécutons-le.

#!/usr/bin/perl

use Employee;

$object = new Employee( "Mohammad", "Saleem", 23234345);
# Get first name which is set using constructor.
$firstName = $object->getFirstName();

print "Before Setting First Name is : $firstName\n";

# Now Set first name using helper function.
$object->setFirstName( "Mohd." );

# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "After Setting First Name is : $firstName\n";

Lorsque nous exécutons le programme ci-dessus, cela produit le résultat suivant -

First Name is Mohammad
Last Name is Saleem
SSN is 23234345
This is child class helper function
Before Setting First Name is : Mohammad
This is child class helper function
After Setting First Name is : Mohd.

Chargement automatique par défaut

Perl offre une fonctionnalité que vous ne trouverez dans aucun autre langage de programmation: un sous-programme par défaut. Ce qui signifie que si vous définissez une fonction appeléeAUTOLOAD(),alors tout appel à des sous-programmes non définis appellera automatiquement la fonction AUTOLOAD (). Le nom du sous-programme manquant est accessible dans ce sous-programme sous la forme $ AUTOLOAD.

La fonctionnalité de chargement automatique par défaut est très utile pour la gestion des erreurs. Voici un exemple pour implémenter AUTOLOAD, vous pouvez implémenter cette fonction à votre manière.

sub AUTOLOAD {
   my $self = shift;
   my $type = ref ($self) || croak "$self is not an object";
   my $field = $AUTOLOAD;
   $field =~ s/.*://;
   unless (exists $self->{$field}) {
      croak "$field does not exist in object/class $type";
   }
   if (@_) {
      return $self->($name) = shift;
   } else {
      return $self->($name);
   }
}

Destructeurs et collecte des ordures

Si vous avez déjà programmé à l'aide de la programmation orientée objet, vous serez conscient de la nécessité de créer un destructorpour libérer la mémoire allouée à l'objet lorsque vous avez fini de l'utiliser. Perl le fait automatiquement pour vous dès que l'objet sort de la portée.

Si vous souhaitez implémenter votre destructeur, qui devrait prendre soin de fermer les fichiers ou d'effectuer un traitement supplémentaire, vous devez définir une méthode spéciale appelée DESTROY. Cette méthode sera appelée sur l'objet juste avant que Perl ne libère la mémoire qui lui est allouée. À tous les autres égards, la méthode DESTROY est comme n'importe quelle autre méthode, et vous pouvez implémenter la logique de votre choix dans cette méthode.

Une méthode destructrice est simplement une fonction membre (sous-programme) nommée DESTROY, qui sera appelée automatiquement dans les cas suivants -

  • Lorsque la variable de la référence d'objet est hors de portée.
  • Lorsque la variable de la référence d'objet n'est pas définie.
  • Lorsque le script se termine
  • Quand l'interpréteur perl se termine

Par exemple, vous pouvez simplement mettre la méthode DESTROY suivante dans votre classe -

package MyClass;
...
sub DESTROY {
   print "MyClass::DESTROY called\n";
}

Exemple de Perl orienté objet

Voici un autre bel exemple, qui vous aidera à comprendre les concepts orientés objet de Perl. Mettez ce code source dans n'importe quel fichier perl et exécutez-le.

#!/usr/bin/perl

# Following is the implementation of simple Class.
package MyClass;

sub new {
   print "MyClass::new called\n";
   my $type = shift;            # The package/type name
   my $self = {};               # Reference to empty hash
   return bless $self, $type;   
}

sub DESTROY {
   print "MyClass::DESTROY called\n";
}

sub MyMethod {
   print "MyClass::MyMethod called!\n";
}


# Following is the implemnetation of Inheritance.
package MySubClass;

@ISA = qw( MyClass );

sub new {
   print "MySubClass::new called\n";
   my $type = shift;            # The package/type name
   my $self = MyClass->new;     # Reference to empty hash
   return bless $self, $type;  
}

sub DESTROY {
   print "MySubClass::DESTROY called\n";
}

sub MyMethod {
   my $self = shift;
   $self->SUPER::MyMethod();
   print "   MySubClass::MyMethod called!\n";
}

# Here is the main program using above classes.
package main;

print "Invoke MyClass method\n";

$myObject = MyClass->new();
$myObject->MyMethod();

print "Invoke MySubClass method\n";

$myObject2 = MySubClass->new();
$myObject2->MyMethod();

print "Create a scoped object\n";
{
   my $myObject2 = MyClass->new();
}
# Destructor is called automatically here

print "Create and undef an object\n";
$myObject3 = MyClass->new();
undef $myObject3;

print "Fall off the end of the script...\n";
# Remaining destructors are called automatically here

Lorsque nous exécutons le programme ci-dessus, cela produit le résultat suivant -

Invoke MyClass method
MyClass::new called
MyClass::MyMethod called!
Invoke MySubClass method
MySubClass::new called
MyClass::new called
MyClass::MyMethod called!
MySubClass::MyMethod called!
Create a scoped object
MyClass::new called
MyClass::DESTROY called
Create and undef an object
MyClass::new called
MyClass::DESTROY called
Fall off the end of the script...
MyClass::DESTROY called
MySubClass::DESTROY called