Que sont les interfaces Java 8 et comment les utilisez-vous ?

En Java, une interface fonctionne à peu près de la même manière qu'une classe abstraite, ce qui signifie qu'un objet ne peut jamais être créé à partir d'une interface. En conséquence, une interface n'a pas de constructeurs, mais elle a des méthodes.

Avant Java 8, une interface pouvait décrire les opérations que sa classe d'implémentation effectuait, mais pas comment la classe d'implémentation devait effectuer cette opération (nous y reviendrons plus tard). Désormais, avec Java 8, un développeur peut faire les deux avec une interface.

C'est parce que Java 8 a introduit des méthodes d'interface par défaut. Ainsi, les développeurs ont désormais la possibilité d'utiliser des méthodes abstraites traditionnelles, ainsi que les nouvelles méthodes concrètes au sein d'une interface. Regardons de plus près.

Qu'est-ce qu'une interface ?

Avant de pouvoir vraiment comprendre le but d'une interface et comment l'utiliser efficacement, vous devez comprendre le polymorphisme. Le polymorphisme est un concept central de la programmation orientée objet, qui permet à un développeur de créer un comportement généralisé et spécialisé avec des classes (qui, dans certains cas, ne sont pas directement liées).

Le principal avantage du polymorphisme est qu'il facilite la réutilisation du code, ce qui est vital dans l'industrie du développement de logiciels d'aujourd'hui.

Connexes : Qu'est-ce que le polymorphisme ? Et pourquoi ça vaut la peine d'apprendre

Alors, comment le polymorphisme se rapporte-t-il à une interface Java ? En Java, une interface permet à des classes qui ne seraient pas conventionnellement liées d'avoir accès à des opérations similaires. Dans sa forme la plus simple, une interface Java est un modèle qui peut être facilement utilisé par les différentes classes qui l'implémentent. Ces classes d'implémentation peuvent ensuite transformer la méthode d'une interface de son état généralisé à un état plus spécialisé pour accomplir une tâche spécifique.

Quels sont les avantages de l'utilisation des interfaces Java 8 ?

L'avantage le plus évident de l'utilisation d'une interface Java 8 est sa nouvelle capacité de méthode concrète.

Un autre avantage bienvenu des interfaces Java 8 est la possibilité d'ajouter de nouvelles méthodes concrètes à une interface existante, qui a déjà été implémentée, sans casser le programme. Avant Java 8, si vous aviez une classe implémentant une interface mais n'utilisant pas toutes ses méthodes, cette classe devrait être étiquetée comme abstraite. Sinon, le programme serait interrompu.

Quand utiliser une interface ?

De nombreux programmes existants peuvent potentiellement utiliser des interfaces Java 8. La fonction d'une interface est de faciliter la vie d'un programmeur. Bien que la même fonctionnalité puisse être obtenue sans interfaces, leur utilisation rendra vos programmes plus organisés et votre processus de développement moins long.

Si vous êtes familier avec l'héritage, sachez qu'il s'agit également d'un concept de base de la programmation orientée objet qui facilite la généralisation. Avec l'héritage, des classes similaires sont regroupées dans des relations parent-enfant.

Avec le polymorphisme (qui est le comportement de programmation qu'une interface présente), les classes qui n'auraient généralement pas accès aux mêmes méthodes (en raison d'un manque de relations parent-enfant), peuvent désormais être traitées de manière polymorphe.

Un exemple pratique d'utilisation d'une interface se trouve au sein du service de comptabilité d'une organisation logicielle. Ce service effectuera très probablement un ensemble des mêmes méthodes (ou opérations) lors de la création du bulletin de paie d'un employé et de la facture d'un client.

Ce sont deux classes qui ne seraient pas liées de manière conventionnelle, mais elles peuvent désormais utiliser certaines des mêmes opérations grâce aux interfaces Java 8.

Création d'une interface en Java

En utilisant le scénario de service comptable ci-dessus, vous pouvez créer une interface qui traite les opérations de paiement. Le but de cette interface est d'aider à la génération des rapports de paiement (sous forme de factures, fiches de paie et autres dépenses).

Création d'un exemple d'interface Java

 //Java interface
public interface Payable {
//abstract method public void paymentAmount();
}

Le code ci-dessus génère une interface Java simple. Le mot-clé interface indique que Payable est une interface et que la méthode paymentAmount() est une méthode abstraite car elle n'est pas implémentée.

Implémentation de l'exemple d'interface payante

 public class Employee implements Payable {
//attributes
private String name; private String position;
//primary constructor
public Employee (String name, String position) {
this.name = name; this.position = position;
}
//payLevel method - takes an employee's position and returns their pay
public double payLevel(String position) {
position.toLowerCase();
if (position == "junior" ) {
return 10.00;
}
if(position == "mid-level") {
return 20.0;
}
if(position == "senior") {
return 30.00;
}
return 0 ;
}
@Override public void paymentAmount() {
//passes the position attribute provided by the user to the payLevel() method above
// store the return from the function call to a double variable called pay
//and print the relevant data to the console
double pay = payLevel(position);
System.out.println(name + " pay for this month is: " + pay);
}
}

Pour utiliser une interface dans une classe, vous devez d'abord implémenter cette interface à l'aide du mot-clé implement , comme vous pouvez le voir dans le code ci-dessus. Après avoir implémenté une nouvelle interface, vous devez créer des méthodes concrètes pour toutes les méthodes abstraites de l'interface, en utilisant le mot-clé @Override .

Connexes : Polymorphisme en Java : comment surcharger ou remplacer des méthodes

Exécution de l'exemple de programme

 public class Main {
public static void main(String[] args) {
//Create a new employee pay report
Payable JanesPay = new Employee ("Jane Doe", "mid-level");
//calculate the employee's pay
JanesPay.paymentAmount();
}
}

Le programme ci-dessus utilise la classe Employé pour générer une nouvelle fiche de paie qui utilise l'interface Payable . Un objet ne peut pas être créé à partir d'une interface, mais un objet peut être déclaré à l'aide d'une interface, comme vous pouvez le voir dans le code ci-dessus.

L'objet de paie de Jeanne est créé à l'aide de deux attributs : le nom d'un employé et le poste de l'employé dans l'entreprise. Il n'y a qu'un seul constructeur principal dans la classe des employés , par conséquent, chaque nouvel objet employé qui est créé doit avoir deux attributs de chaîne.

À l'aide de l'objet Jane's pay , le programme appelle la méthode paymentAmount() dans la classe employee , qui produit la sortie suivante dans la console :

 Jane Doe pay for this month is: 20.0

Exemple de mise en œuvre de l'interface payable avec le client

 public class Customer implements Payable{
private String customerName;
private String projectType;
public Customer(String customerName, String projectType) {
this.customerName = customerName;
this.projectType = projectType;
}
public double customerInvoice(String projectType) {
projectType.toLowerCase();
if (projectType == "small" ) {
return 10.00;
}
if(projectType == "medium") {
return 20.0;
}
if(projectType == "large") {
return 30.00;
}
return 0 ;
}
@Override public void paymentAmount() {
double total = customerInvoice(projectType);
System.out.println(customerName + " total charge for services provided is: " + total);
}
}

Les classes d' employés et de clients ne sont pas liées les unes aux autres, mais parce qu'elles implémentent chacune la même interface, elles ont désormais accès à des opérations similaires. Comme la classe des employés , la classe des clients doit implémenter l'interface et remplacer la méthode abstraite paymentAmount() pour fonctionner correctement.

Désormais, les mêmes opérations qui ont été effectuées sur un objet de la classe employé , peuvent également être effectuées sur un objet de la classe client .

Création d'un exemple d'objet client

 public class Main {
public static void main(String[] args) {
//Create a new customer invoice report
Payable PaulsInvoice = new Customer("Paul Smith", "large");
//calculate the customer's pay
PaulsInvoice.paymentAmount();
}
}

Le code ci-dessus génère la sortie suivante dans la console :

 Paul Smith total charge for services provided is: 30.0

Étant donné que l'interface est une interface Java 8, vous pouvez y ajouter des méthodes par défaut sans casser le code, comme vous pouvez le voir dans l'exemple ci-dessous.

Mise à jour d'un exemple d'interface Java 8

 //Java interface
public interface Payable {
//abstract method
public abstract void paymentAmount();
//concrete method
public default void companyName() {
System.out.println("Software Company");
}
}

Avant Java 8, l'ajout de la méthode concrète dans le code ci-dessus à votre interface casserait l'interface. C'est parce que les interfaces avant Java 8 ne pouvaient pas avoir de méthodes concrètes. Cependant, si la méthode était abstraite, l'interface resterait inchangée. Mais les classes qui l'ont implémenté avant l'ajout de la nouvelle méthode s'effondreraient.

Désormais, grâce à Java 8, l'ajout de méthodes concrètes à une interface ne cassera pas les classes déjà implémentées. Par conséquent, les objets créés à partir de l'une des deux classes d'implémentation de cet exemple de gestion de compte peuvent utiliser la méthode companyName() sans modifier leur code existant.

Utilisation de l'exemple de méthode par défaut de l'interface Java 8

 public class Main {
public static void main(String[] args) {
//Create a new employee pay report
Payable JanesPay = new Employee("Jane Doe", "mid-level");
//call the default method from the interface
JanesPay.companyName();
//calculate the employee's pay
JanesPay.paymentAmount();
}
}

Le code ci-dessus produira ce qui suit dans la console :

 Software Company
Jane Doe pay for this month is: 20.0

Utiliser la généralisation pour créer du code réutilisable

Vous pouvez désormais utiliser des opérations similaires pour les classes qui ne sont pas conventionnellement liées à l'aide des interfaces Java 8. Vous avez également la possibilité et les connaissances nécessaires pour utiliser des méthodes concrètes et abstraites dans vos interfaces.

Mais pour les classes qui sont liées de manière conventionnelle, vous pouvez apprendre à réutiliser le code avec héritage.