• Aucun résultat trouvé

Le polymorphisme d’interface

Comme nous l’avons dit, une interface est un contrat de comportement.

C’est en quelque sorte une garantie que si une classe implémente comme il faut cette interface, elle aura le comportement adéquat lorsqu’on l’utilisera dans les bonnes conditions.

Une interface se contente de donner la liste des membres à implémenter.

Elle n’impose aucune contrainte sur la manière dont est faite cette implémentation.

De plus, il n’y a pas de limite au nombre de classes qui l’implémente.

L’interface définit juste un comportement. Elle n’agit pas elle-même.

Elle permet juste de mettre en relation différents éléments. Il peut y avoir plusieurs classes qui implémentent une interface, une seule, voire aucune.

En revanche, il n’y a pas de limite au nombre d’interfaces qu’une classe implémente. Par exemple, un bateau peut avoir à la fois un comportement de transporteur de passagers et un comportement de véhicule de course s’il est puissant et léger.

Il y a trois grandes étapes dans l’utilisation d’un polymorphisme d’interface :

La programmation orientée objet Chapitre 9

181 LE GUIDE COMPLET

j Tout d’abord, il faut définir l’interface, c’est-à-dire l’ensemble des membres que devront implémenter les classes pour être considéré en tant que tel.

j Ensuite, il faut implémenter ces membres dans les classes correspondantes.

j Dès lors, on peut utiliser l’interface comme un intermédiaire entre les différents membres à mettre en relation, sans se soucier de l’implémentation. En effet, étant donné qu’ils implémentent bien l’interface en question, on peut être sûr de leur comportement.

Première étape : la définition de l’interface

Une interface se définit avec le mot-cléInterface. Par convention, le nom d’une interface commence toujours par unI majuscule.

À l’intérieur, il faut mettre les membres qui composeront cette interface.

Ce sont généralement des méthodes qui traduisent le comportement.

Cependant, on ne peut pas mettre des attributs. Cela empêche qu’un élément mis en relation avec une classe qui implémente cette interface puisse agir directement sur les données internes de celle-ci.

Pour les méthodes, il suffit juste d’en donner le nom et la signature. Par contre, on peut mettre des propriétés, à définir en lecture seule ou en écriture seule.

Pour illustrer ce principe, examinons le problème de transport de passagers dans différents véhicules. Le transport est possible en avion, en voiture, en train, etc. Vous allez étudier comment cela se passe au niveau de chaque élément.

Public Class Personne Public nom As String End Class

Public Interface ITransporteur

Sub prendPassager(passager As Personne) Sub deposePassager(passager As Personne) Sub allerVers(ByVal destination As String) End Interface

La première partie n’est pas importante. Elle définit simplement une personne représentant le passager que le véhicule devra transporter.

Ensuite, l’interface ITransporteur est définie. Maintenant, pour qu’un véhicule soit considéré comme un transporteur potentiel de passagers, il faudra que la classe implémente une méthode

Passer au niveau supérieur Chapitre 9

prendPassager, ayant pour paramètre une personne, une méthode deposePassager, avec le même paramètre, et enfin une méthode allerVersdont le paramètre est une chaîne de caractères représentant la ville de destination.

Cette partie est la plus simple dans l’utilisation du polymorphisme d’interface. Voyons maintenant ce qu’il faut faire au niveau des classes qui veulent l’implémenter.

Deuxième étape : l’implémentation de l’interface dans les classes

Considérons deux classes de véhicules, les avions et les bateaux, avec chacune leur comportement de base :

Public Class Avion

Private altitude As Integer Private destination As String Public Sub decoller()

Public Sub changerCap(ByVal ville As String) Me.destination = ville

End Sub End Class

Public Class Bateau

Private destination As String

Public Sub naviguer(ByVal ville As String) End Sub

End Class

Vous avez l’implémentation de deux classes de véhicules, ayant chacune leurs spécificités. En effet, l’avion doit gérer son altitude, contrairement au bateau qui ne bouge pas en hauteur. Au niveau du bateau, on dit qu’il navigue, alors que l’avion change de cap.

Pour l’instant, aucune d’entre elles n’implémente l’interface définie précédemment et aucune n’est donc en mesure d’être en relation avec des éléments relatifs aux transporteurs de personnes.

La programmation orientée objet Chapitre 9

183 LE GUIDE COMPLET

L’implémentation de l’interface se passe en deux étapes :

j D’abord, on précise que la classe implémente l’interface.

j Puis, il faut créer une implémentation de chaque membre de l’interface dans la classe.

La partie relative à l’interface elle-même est simple. Il suffit d’utiliser le mot-cléImplements avec le nom de l’interface :

Public Class Avion

Implements ITransporteur Private altitude As Integer Private destination As String Public Sub decoller()

Public Sub changerCap(ByVal ville As String) Me.destination = ville

End Sub End Class

Public Class Bateau

Implements ITransporteur Private destination As String

Public Sub naviguer(ByVal ville As String) Me.destination = ville

End Sub End Class

Si la classe implémente plusieurs interfaces, celles-ci sont séparées par des virgules (on considère que les autres interfaces existent, même si l’on ne les utilise pas ici).

Public Class Avion

Implements Itransporteur, IObjetVolant Private altitude As Integer

[…]

End Class

Public Class Bateau

Implements Itransporteur, IObjetFlottant Private destination As String

[…]

End Class

Passer au niveau supérieur Chapitre 9

Maintenant que vous avez spécifié que les classes devaient implémenter l’interfaceITransporteur, il faut implémenter chacun des membres, à savoir les méthodesprendsPassager,deposePassager,allerVers. Pour cela, on utilise également le mot-cléImplements, et l’on précise quel membre de l’interface le membre créé implémente. À part cela, il s’agit d’une méthode classique. Attention, pour garantir un bon comportement, il peut être nécessaire de modifier le comportement du reste de la classe. Ici, on ajoutera un attribut passager de type Personnepour garder un comportement valable.

Public Class Avion

Implements ITransporteur

Private passagerABord As Personne Private altitude As Integer Private destination As String Public Sub decoller()

Public Sub changerCap(ByVal ville As String) Me.destination = ville

End Sub

Public Sub prendsPassager(passager As Personne) _ Implements ITransporteur.prendsPassager

Me. passagerABord = passager End Sub

Public Sub deposePassager(passager As Personne) _ Implements ITransporteur. deposePassager

If (Me.passagerABord.nom = passager.nom) Me.passagerABord = ""

EndIf End Sub

Public Sub allerVers(ByVal ville As String) _ Implements ITransporteur.allerVers

La programmation orientée objet Chapitre 9

185 LE GUIDE COMPLET

Public Class Bateau

Implements Itransporteur

Private passagerABord As Personne Private destination As String

Public Sub naviguer(ByVal ville As String) Me.destination = ville

End Sub

Public Sub prendsPassager(passager As Personne) _ Implements ITransporteur.prendsPassager

Me. passagerABord = passager End Sub

Public Sub deposePassager(passager As Personne) _ Implements ITransporteur. deposePassager

If (Me.passagerABord.nom = passager.nom) Me.passagerABord = ""

EndIf End Sub

Public Sub allerVers(ByVal ville As String) _ Implements ITransporteur.allerVers

Me.naviguer(ville) End Sub

End Class

Maintenant, les deux classesBateauetAvionimplémentent totalement l’interface ITransporteur. Les implémentations se ressemblent. En ce qui concerne le passager, le code est identique. Concernant le transport vers la destination, la différence est que l’avion doit décoller et atterrir. Cela n’a pas d’importance. Comme nous l’avons précisé, l’interface force juste un comportement et n’impose aucune contrainte sur sa "réalisation". Les réalisations auraient pu être identiques ou différentes, cela ne remet pas en question le fait que maintenant,Avion etBateausont considérés comme desITransporteur.

Dernière étape : l’utilisation de l’interface comme intermédiaire

Maintenant que les classesAvionetBateauont implémenté l’interface ITransporteur, elles peuvent dialoguer directement avec n’importe quel élément qui attendrait unITransporteur.

Prenons par exemple une fonctionvoyage, qui emmène une personne à un endroit donné, grâce à un transporteur :

Passer au niveau supérieur Chapitre 9

Public Sub voyage(voyageur As Personne, _ ByVal transport As ITransporteur, _ ByVal ville As String)

End Sub

Étant donné que l’on connaît le comportement de toute classe qui implémente l’interface ITransporteur, on peut utiliser cela pour définir la fonctionvoyage:

Public Sub voyage(voyageur As Personne, _ ByVal transport As ITransporteur, _ ByVal ville As String)

Transport.prendsPassager(voyageur) Transport.allerVers(ville)

Transport.deposePassager(voyageur) End Sub

Pour pouvoir utiliserAvionetBateauen tant queITransporteur, il y a une petite opération supplémentaire à réaliser. Il faut convertir explicitement les objets enITransporteur. Pour faire cela, on utilise la fonction de conversionCType:

Dim monAvion As New Avion() Dim monBateau As New Bateau()

Dim monAvionTransporteur As ITransporteur Dim monBateauTransporteur As ITransporteur

monBateauTransporteur = CType(ITransporteur, monBateau) monAvionTransporteur = CType(ITransporteur, monAvion)

Vous avez accompli toutes les étapes pour pouvoir utiliser Avion et Bateau comme des transporteurs de personnes. Maman veut aller à New York en avion :

Dim maman As Personne() Dim monAvion As Avion()

Dim transporteur As ITransporteur Dim ville As String

ville = "New York"

maman.nom = "Maman"

transporteur = CType(ITransporteur, monAvion) voyage(maman, transporteur, ville)

Si elle avait voulu partir en bateau, rien de plus simple :

Dim maman As Personne() Dim monBateau As Bateau()

Dim transporteur As ITransporteur Dim ville As String

ville = "New York"

maman.nom = "Maman"

transporteur = CType(ITransporteur, monBateau)

La programmation orientée objet Chapitre 9

187 LE GUIDE COMPLET

voyage(maman, transporteur, ville)

Seules deux lignes ont été modifiées, et pourtant le moyen a totalement changé. Vous avez modifié deux appels, tout en garantissant une cohérence et une fiabilité des opérations effectuées. Cet exemple montre l’intérêt du polymorphisme d’interface. C’est un mécanisme subtil et bien pratique une fois maîtrisé.