Voir le flux RSS

François DORIN

[Actualité] C# : Implémentation explicite des interfaces - Partie 3

Note : 3 votes pour une moyenne de 5,00.
par , 16/08/2018 à 22h25 (4223 Affichages)
Ce billet s'inscrit dans une série de billets autour de l'implémentation explicite des interfaces en C#.

Dans le premier billet, nous avons vu qu'il existe deux manières d'implémenter une interface en C#. De manière implicite (la voie "classique") et de manière explicite. Le billet était illustré par un exemple d'utilisation, avec la "surcharge" d'une méthode en modifiant uniquement son type de retour.

Dans le second billet, nous avons abordé un autre de ces cas d'usage : le masquage d'une méthode.

Dans ce troisième billet, nous allons étudier une autre utilisation possible : implémenter des interfaces définissant les mêmes méthodes, mais avec des sémantiques différentes.

Nom : logo-csharp.png
Affichages : 1805
Taille : 50,9 Ko

Multiples interfaces... une méthode
Que se passe-t-il si une classe doit implémenter deux interfaces qui définissent la même méthode ?

Prenons l'exemple suivant :
Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public interface ITemperatureCelsius
{
   float GetTemperature();
}
 
public interface ITemperatureKelvin
{
   float GetTemperature();
}
 
public interface ITemperatureFarhenheit
{
   float GetTemperature();
}
 
public class Temperature : ITemperatureCelsius, ITemperatureKelvin, ITemperatureFarhenheit
{
   private float _temperature;
 
   public Temperature(float temperature)
   {
      _temperature= temperature;
   }
 
   public float GetTemperature()
   {
     return _temperature;
   }
}

Ce code compile correctement, mais est-il correct pour autant ? La réponse est non.

Non, car si la classe implémente bien les différentes interfaces, on constate que la même implémentation implicite est partagée par les 3 interfaces. Pourtant, nous savons bien qu'une température en degré Celsius, degré Kelvin ou degré Farenheit, même si elles sont liées, ne sont pas égales.

Comment faire donc pour résoudre ce cas ? Utilisons l'implémentation explicite des interfaces !

Rappel métrologique
Sans rentrer dans les détails (les pages Wikipédia consacré au degré Farhenheit et degré Kelvin feront très bien l'affaire), je rappelle juste ici les formules qui nous seront utiles pour la suite du billet :
  • Celsius vers Farhenheit : Formule mathématique
  • Farhenheit vers Celsius : Formule mathématique
  • Celsius vers Kelvin : Formule mathématique
  • Kelvin vers Celsius : Formule mathématique


Implémentation explicite à la rescousse
Utilisons l'implémentation explicite pour implémenter chacune des interfaces. Au passage, rendons le constructeur privé, et définissons des méthodes statiques pour instancier des températures en utilisant le référentiel souhaité.

Nous obtenons donc :
Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class Temperature : ITemperatureCelsius, ITemperatureKelvin, ITemperatureFarenheit
{
   private float _temperature; // La température est stockée en Celsius
 
   private Temperature(float temperature)
   {
      _temperature = temperature;
   }
 
   public static FromCelsius(float celsius)
   {
      return new Temperature(celsius);
   }
 
   public static FromKelvin(float kelvin)
   {
      return new Temperature(kelvin + 273.15);
   }
 
   public static FromFarhenheit(float farhenheit)
   {
      return new Temperature((farhenheit - 32) / 1.8);
   }
 
   float ITemperatureCelsius.GetTemperature()
   {
     return _temperature;
   }
 
   float ITemperatureKelvin.GetTemperature()
   {
      return _temperature - 273.15;
   }
 
   float ITemperatureFehrenheit.GetTemperature()
   {
      return _temperature * 1.8 + 32;
   }
}

Nous avons ainsi défini une classe permettant de faire facilement des conversions de température.
Son utilisation est des plus simples :
Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
Temperature t = Temperature.FromCelsius(25);
float t_C = (t as ITemperatureCelsius).GetTemperature();
float t_K = (t as ITemperatureKelvin).GetTemperature();
float t_F = (t as ITemperatureFahrenheit).GetTemperature();


Conclusions
Nous venons de voir un cas d'usage supplémentaire de l'instanciation explicite : le cas où plusieurs interfaces définissent la même méthode.

Il y a de nombreuses situations où cela peut servir. Dans un cas de conversion d'unité par exemple (comme l'exemple ci-dessus). Mais il peut arriver également que deux interfaces définissent la même méthode avec une sémantique totalement différente. L'instanciation explicite nous permet alors de répondre à cette problématique.

Envoyer le billet « C# : Implémentation explicite des interfaces - Partie 3 » dans le blog Viadeo Envoyer le billet « C# : Implémentation explicite des interfaces - Partie 3 » dans le blog Twitter Envoyer le billet « C# : Implémentation explicite des interfaces - Partie 3 » dans le blog Google Envoyer le billet « C# : Implémentation explicite des interfaces - Partie 3 » dans le blog Facebook Envoyer le billet « C# : Implémentation explicite des interfaces - Partie 3 » dans le blog Digg Envoyer le billet « C# : Implémentation explicite des interfaces - Partie 3 » dans le blog Delicious Envoyer le billet « C# : Implémentation explicite des interfaces - Partie 3 » dans le blog MySpace Envoyer le billet « C# : Implémentation explicite des interfaces - Partie 3 » dans le blog Yahoo

Mis à jour 23/08/2018 à 23h26 par François DORIN

Catégories
DotNET , C#

Commentaires