Les interfaces
Explication et utilisation des interfaces
23/03/2009
7632 lectures
5 commentaires
4.77/5 (13 votes)
Nous allons maintenant aborder une notion qui, à première vue, semble assez inutile, mais en fin de compte elle se révèle très importante et utile. Une interface est une sorte de classe mais qui ne contient que les signatures des méthodes, propriétés, événements,... Une interface ne peut donc contenir aucune implémentation. Nous allons voir après la théorie à quoi peut bien servir un tel type de classe. Mais avant, voyons comment déclarer une interface :
De cette façon, nous déclarons une interface nommée Interface. Pour ce qui est de la convention de nommmage des interfaces, nous vous conseillons de débuter le nom de vos interfaces par I. Le Framework .NET propose par exemple les interfaces IComparable, IDisposable,... Voici par exemple comment déclarer une interface contenant une fonction :
Ceci n'est qu'un exemple mais cela vous permet de définir une interface contenant la signature d'une fonction nommée foo, renvoyant un int et attendant un string en paramètre. Vous devez vous demander à quoi sert ce type de classe, nous allons voir cela à l'aide d'un exemple assez simple dans lequel nous utiliserons une interface déjà programmée. Cette interface se nomme IComparable. Le but de notre exemple sera assez simple. Nous allons tout d'abord créer une classe Actor qui va permettre de contenir des acteurs de cinéma. Nous allons alors créer 3 objets de ce type et les placer dans une liste, enfin, nous allons utiliser la méthode Sort de la liste pour trier les acteurs sur base de leur age. Nous verrons à quoi sert l'interface et comment l'utiliser. Commencez par créer une nouvelle application console et ajoutez-y une nouvelle classe nommée Actor :
Bon pour l'instant, il n'y a rien de bien compliqué. Nous avons déclaré une classe Actor qui contient le nom, le prénom et l'age d'un acteur et qui redéfini également la méthode ToString pour afficher notre acteur de manière adéquate. Passez maintenant au code de la fonction Main dans laquelle nous allons essayer d'utiliser cette classe :
Si vous tentez d'exécuter votre programme, vous risquez d'obtenir ceci :
Regardons plus attentivement le code que nous avons utilisé précédemment pour voir d'où vient l'erreur. Tout d'abord, nous déclarons une liste contenant des objets du type Actor. Nous ajoutons ensuite 3 objets de ce type dans cette liste. Jusque là, aucune exception n'est lancée, nous bouclons ensuite sur les éléments de la liste pour les afficher les uns après les autres. Ensuite, nous appelons la fonction Sort de la liste et c'est là que le problème survient. Les plus perspicaces d'entre vous auront compris ce qui ne va pas. Effectivement, ici, nous voulons trier les éléments de la liste sur base de leur age, mais ça, le programme ne le sait pas. Effectivement, il est impossible pour le programme de définir quel objet Actor est le plus grand car il ne sait pas sur base de quelle propriété la comparaison doit s'opérer.
La fonction Sort fonctionne assez simplement. Elle va tenter de trier la liste en ordre décroissant en effectuant des comparaisons des objets contenus dans la liste. De cette manière, la fonction déterminera l'ordre dans lequel les objets devront être triés, mais pour cela, la fonction Sort doit pouvoir comparer deux objets ensemble et savoir quel est le plus grand, c'est là que l'interface intervient. Une interface doit être vue comme un contrat. Une classe dérivant de l'interface IFoo certifie que cette classe implémente toutes les fonctions déclarées dans l'interface IFoo. Effectivement, une interface ne contenant que la déclaration de ses membres, il est impossible d'instancier une interface, la seule possibilité consiste à créer une classe dérivant de cette interface et implémentant tous ses membres. Bien qu'une classe ne puisse dériver que d'une seule autre classe, elle peut dériver de plusieurs interfaces.
Pour en revenir à notre exemple, la fonction Sort va utiliser la fonction CompareTo sur les objets contenus dans la liste, pour cela, ces objets doivent certifier qu'ils implémentent cette fonction. Pour cela, il suffit de faire dériver notre classe Actor de la classe IComparable. Une classe implémentant cette interface assure qu'elle redéfinit la fonction CompareTo qui va permettre de renvoyer un résultat indiquant le résultat de la comparaison des deux objets. La fonction Sort, voyant que les objets Actor dérivent de IComparable, va savoir qu'il lui suffit d'appeler la fonction CompareTo de ces objets pour avoir un résultat de la comparaison qu'elle pourra exploiter pour le tri des données. Revenez donc dans votre classe Actor et modifiez sa déclaration de la sorte :
Comme vous le voyez, dériver d'une interface est aussi facilement réalisable que dériver d'une classe. Bien entendu, ce n'est pas terminé, maintenant que notre classe dérive de IComparable, nous allons devoir redéfinir CompareTo. La signature de cette fonction est définie dans l'interface IComparable et ne peut donc pas être modifiée, cela assure à la fonction Sort que la valeur renvoyée par cette fonction sera toujours de type int. Cette fonction va devoir renvoyer -1 si l'objet auquel on compare un autre objet est inférieur à celui-ci, elle devra renvoyer 1 si il est supérieur ou 0 si il est égal. Implémentez donc la fonction de cette manière :
La première chose à faire dans cette fonction est de vérifier si l'objet comparé est bien du type de l'objet auquel on le compare. Nous vérifions donc que l'objet est de type Actor grâce à l'opérateur is. Si ce n'est pas le cas, nous lançons une exception le signalant. Si l'objet passé en paramètre est bien du type Actor, nous plaçons la référence de celui-ci dans un objet du type Actor nommé actor. Ensuite, nous comparons la valeur de la propriété Age des deux objets. Le premier objet est bien entendu this qui représente l'objet courant. Si les valeurs des propriétés Age de ces 2 objets sont égales, nous renvoyons 0, si la valeur de la propriété Age de l'objet passé en paramètre est supérieure à celle de la propriété Age de l'objet courant, nous renvoyons 1, sinon, nous renvoyons -1. Si vous exécutez à nouveau votre programme, vous devriez obtenir ceci :
Comme vous le voyez, notre liste est maintenant bien triée. Effectivement, quand nous appelons la fonction Sort, celle-ci va tenter de trier les éléments de la liste en utilisant la fonction CompareTo des objets contenus dans la liste. Pour cela, la fonction Sort doit avoir la certitude que ces objets offrent une implémentation adéquate de la fonction CompareTo, pour cela, il faut dériver notre classe de IComparable, ainsi la fonction Sort va utiliser la fonction CompareTo de notre objet pour comparer les objets entre eux et finalement les trier de la façon que l'on espère.
De cette façon, nous déclarons une interface nommée Interface. Pour ce qui est de la convention de nommmage des interfaces, nous vous conseillons de débuter le nom de vos interfaces par I. Le Framework .NET propose par exemple les interfaces IComparable, IDisposable,... Voici par exemple comment déclarer une interface contenant une fonction :
Ceci n'est qu'un exemple mais cela vous permet de définir une interface contenant la signature d'une fonction nommée foo, renvoyant un int et attendant un string en paramètre. Vous devez vous demander à quoi sert ce type de classe, nous allons voir cela à l'aide d'un exemple assez simple dans lequel nous utiliserons une interface déjà programmée. Cette interface se nomme IComparable. Le but de notre exemple sera assez simple. Nous allons tout d'abord créer une classe Actor qui va permettre de contenir des acteurs de cinéma. Nous allons alors créer 3 objets de ce type et les placer dans une liste, enfin, nous allons utiliser la méthode Sort de la liste pour trier les acteurs sur base de leur age. Nous verrons à quoi sert l'interface et comment l'utiliser. Commencez par créer une nouvelle application console et ajoutez-y une nouvelle classe nommée Actor :
Bon pour l'instant, il n'y a rien de bien compliqué. Nous avons déclaré une classe Actor qui contient le nom, le prénom et l'age d'un acteur et qui redéfini également la méthode ToString pour afficher notre acteur de manière adéquate. Passez maintenant au code de la fonction Main dans laquelle nous allons essayer d'utiliser cette classe :
Si vous tentez d'exécuter votre programme, vous risquez d'obtenir ceci :
Regardons plus attentivement le code que nous avons utilisé précédemment pour voir d'où vient l'erreur. Tout d'abord, nous déclarons une liste contenant des objets du type Actor. Nous ajoutons ensuite 3 objets de ce type dans cette liste. Jusque là, aucune exception n'est lancée, nous bouclons ensuite sur les éléments de la liste pour les afficher les uns après les autres. Ensuite, nous appelons la fonction Sort de la liste et c'est là que le problème survient. Les plus perspicaces d'entre vous auront compris ce qui ne va pas. Effectivement, ici, nous voulons trier les éléments de la liste sur base de leur age, mais ça, le programme ne le sait pas. Effectivement, il est impossible pour le programme de définir quel objet Actor est le plus grand car il ne sait pas sur base de quelle propriété la comparaison doit s'opérer.
La fonction Sort fonctionne assez simplement. Elle va tenter de trier la liste en ordre décroissant en effectuant des comparaisons des objets contenus dans la liste. De cette manière, la fonction déterminera l'ordre dans lequel les objets devront être triés, mais pour cela, la fonction Sort doit pouvoir comparer deux objets ensemble et savoir quel est le plus grand, c'est là que l'interface intervient. Une interface doit être vue comme un contrat. Une classe dérivant de l'interface IFoo certifie que cette classe implémente toutes les fonctions déclarées dans l'interface IFoo. Effectivement, une interface ne contenant que la déclaration de ses membres, il est impossible d'instancier une interface, la seule possibilité consiste à créer une classe dérivant de cette interface et implémentant tous ses membres. Bien qu'une classe ne puisse dériver que d'une seule autre classe, elle peut dériver de plusieurs interfaces.
Pour en revenir à notre exemple, la fonction Sort va utiliser la fonction CompareTo sur les objets contenus dans la liste, pour cela, ces objets doivent certifier qu'ils implémentent cette fonction. Pour cela, il suffit de faire dériver notre classe Actor de la classe IComparable. Une classe implémentant cette interface assure qu'elle redéfinit la fonction CompareTo qui va permettre de renvoyer un résultat indiquant le résultat de la comparaison des deux objets. La fonction Sort, voyant que les objets Actor dérivent de IComparable, va savoir qu'il lui suffit d'appeler la fonction CompareTo de ces objets pour avoir un résultat de la comparaison qu'elle pourra exploiter pour le tri des données. Revenez donc dans votre classe Actor et modifiez sa déclaration de la sorte :
Comme vous le voyez, dériver d'une interface est aussi facilement réalisable que dériver d'une classe. Bien entendu, ce n'est pas terminé, maintenant que notre classe dérive de IComparable, nous allons devoir redéfinir CompareTo. La signature de cette fonction est définie dans l'interface IComparable et ne peut donc pas être modifiée, cela assure à la fonction Sort que la valeur renvoyée par cette fonction sera toujours de type int. Cette fonction va devoir renvoyer -1 si l'objet auquel on compare un autre objet est inférieur à celui-ci, elle devra renvoyer 1 si il est supérieur ou 0 si il est égal. Implémentez donc la fonction de cette manière :
La première chose à faire dans cette fonction est de vérifier si l'objet comparé est bien du type de l'objet auquel on le compare. Nous vérifions donc que l'objet est de type Actor grâce à l'opérateur is. Si ce n'est pas le cas, nous lançons une exception le signalant. Si l'objet passé en paramètre est bien du type Actor, nous plaçons la référence de celui-ci dans un objet du type Actor nommé actor. Ensuite, nous comparons la valeur de la propriété Age des deux objets. Le premier objet est bien entendu this qui représente l'objet courant. Si les valeurs des propriétés Age de ces 2 objets sont égales, nous renvoyons 0, si la valeur de la propriété Age de l'objet passé en paramètre est supérieure à celle de la propriété Age de l'objet courant, nous renvoyons 1, sinon, nous renvoyons -1. Si vous exécutez à nouveau votre programme, vous devriez obtenir ceci :
Comme vous le voyez, notre liste est maintenant bien triée. Effectivement, quand nous appelons la fonction Sort, celle-ci va tenter de trier les éléments de la liste en utilisant la fonction CompareTo des objets contenus dans la liste. Pour cela, la fonction Sort doit avoir la certitude que ces objets offrent une implémentation adéquate de la fonction CompareTo, pour cela, il faut dériver notre classe de IComparable, ainsi la fonction Sort va utiliser la fonction CompareTo de notre objet pour comparer les objets entre eux et finalement les trier de la façon que l'on espère.



5 commentaires
Stef a dit:
Un grand merci !
Nouwara a dit:
Merci!
phaso a dit:
cool
hassen a dit:
très bien expliqué!
merci
Rossi a dit:
J'ai enregistré ce petit tuto il y a quelques mois.
Je le relis avec plaisir aujourd'hui.
Merci
Ajouter un commentaire