====== Objets ====== ====== 1. Programmation orientée objet ====== ===== Paradigme ===== Plutôt que de considérer un programme comme une suite d'actions manipulant des données quelconques, la programmation OO propose de centrer sa vision autour de ce qui est manipulé. Un programme OO va alors se soucier du cycle de vie de ses objets: on les crée, on les utilise, puis éventuellement on les détruit. Cela implique dans un programme de se soucier de la donnée avant de la manipuler, comme on le fait déjà pour la déclaration et l'initialisation. La création d'un objet peut être considéré comme une initialisation sophistiquée et sur mesure : my $file = FileHandle->new(">sortie.txt"); # my $file; open($file, ">sortie.txt"); my $line = $file->getline(); # my $line = <$file>; $file->close(); # close($file); ===== Classe et instance ===== Une classe décrit l'interface que pourra accepter un type d'interface, on y trouve : * **les méthodes**: ce sont les actions que l'on peut effectuer sur un objet (ex: //$file->close()//) * **les attributs**: comparables à des variables, on peut les lire et écrire (ex: //$eleve->nom//) En général, il n'est pas possible d'invoquer ces méthode et attributs sans désigner un objet qui a été dûment créé: cet objet est appelé une instance de la classe qui le décrit. On est dans une situation comparable au type et à la variable. Dans le dernier exemple, //FileHandle// est la classe et //$file// est l'objet. On utilise souvent de manière interchangeable les mots //objet// et //instance//. **Note**: dans certains cas, il est possible d'invoquer une méthode "de classe", sans l'existence d'un objet particulier (par exemple pour la création de l'objet lui-même). ===== Héritage ===== Une classe est en général définie comme le cumul de fonctions de classes existantes, plus des nouvelles fonctionnalités. Cette conception "par couche", où l'on peut empiler les fonctions pour créer des classes plus sophistiquées (ou plus spécialisées) est appelée l'héritage. my $mirza = Chien->new(); $mirza->aboie(); my $medor = ChientMechant->new(); # ChientMechant "hérite de" Chien $medor->aboie(); # donc il peut en particulier aboyer, comme tout "Chien" $medor->attaque(); # mais il peut aussi attaquer! ====== 2. Utilisation des objets en Perl ====== La majorité des modules du répertoire CPAN sont fournis sous forme de classes, il faut donc en général commencer par instancier des objets pour pouvoir accéder à leurs fonctionnalités. Par convention (et il ne s'agit que d'une convention), le constructeur est en général est la méthode //new()//. Il y a bien sûr des exceptions : use DBI; my $db = DBI->connect($dsn, $user, $password); Un objet en Perl est une référence sur une structure quelconque (scalaire, liste, tableau, etc), qu'on a en plus associé à une classe particulière (nous verrons comment en concevant nos propres objets). Ainsi ces deux éléments sont différents : my $mirza = Chien->new(); print "Ce chien s'appelle: ".$mirza->name(); # Il s'agit de la méthode 'name' print "Ce chien s'appelle: ".$mirza->{'name'}; # Il s'agit de l'élément 'name' du tableau %{$mirza} Il est assez courant que les paramètres d'un constructeur soient passés sous la forme d'un tableau (associatif), ceci rendant plus lisible l'utilisation de l'objet. Dans ce cas on veille bien à utiliser une référence vers un tableau : use DBIx::SearchBuilder::Handle; my $handle = DBIx::SearchBuilder::Handle->new(); $handle->Connect({ Driver => 'SQLite', Database => "my_test_db" }); Profitez de l'héritage: quand vous manipulez un objet de la classe **Toto**, vous avez le droit d'utiliser les méthodes de tout ses "parents". ===== Exemple ===== ==== Création d'un module ==== * **Fichier classe : //modules/joueur.pm//** package joueur; use strict; use warnings; our $info="Fichier classe : " . __FILE__ . "\nNom classe : " . __PACKAGE__ . "\nLigne : " . __LINE__ . "\n\n"; #constructeur sub new { my ( $classe, $nom ) = @_; #on passe les données au constructeur my $this = { "joueur" => "$nom", "x" => 0, "y" => 0 }; bless( $this, $classe ); #lie la référence à la classe return $this; #on retourne la référence consacrée } sub avance { my ( $this, $nb_case ) = @_; $this->{y} += $nb_case; } sub recule { my ( $this, $nb_case ) = @_; $this->{y} -= $nb_case; } sub tourne_gauche { my ( $this, $nb_case ) = @_; $this->{x} -= $nb_case; } sub tourne_droite { my ( $this, $nb_case ) = @_; $this->{x} += $nb_case; } sub position { my $this = shift; print "Joueur $this->{joueur} se situe x=$this->{x} y=$this->{y}\n"; } sub AUTOLOAD { our $AUTOLOAD; print "ERREUR : La fonction $AUTOLOAD n'a pas été définie !\n"; } # Destructeur sub DESTROY { my $this = shift; print "$this->{joueur} : Partie terminée...\n"; } 1; ==== Utilisation du module et de ses classes ==== * **Programme principal :** #!/usr/bin/perl -w use lib "./modules"; use joueur; print $joueur::info; my $p1 = joueur->new("Joueur1"); my $p2 = joueur->new("Joueur2"); $p1->avance(3); $p1->avance(8); $p1->tourne_gauche(10); $p1->recule(6); $p1->tourne_droite(5); $p2->avance(8); $p2->avance(4); $p2->tourne_gauche(1); $p2->recule(5); $p2->tourne_droite(9); $p1->position; $p2->position; $p2->mourir;