Lors d'un de mes entretiens, on m'a demandé d'expliquer la différence entre une Interface et une Classe abstraite.
Voici ma réponse :
Les méthodes d'une interface Java sont implicitement abstraites et ne peuvent pas être implémentées. Une classe abstraite Java peut avoir des méthodes d'instance qui implémentent un comportement par défaut.
Les variables déclarées dans une interface Java sont par défaut finales. Une classe abstraite classe abstraite peut contenir des variables non finales.
Les membres d'une interface Java sont publics par défaut. Une classe abstraite Java Java peut avoir les saveurs habituelles des membres de classe comme private, protected, etc.
Une interface Java doit être implémentée en utilisant le mot clé "implements". classe abstraite Java doit être étendue en utilisant le mot clé "extends".
Une interface ne peut étendre qu'une autre interface Java, une classe abstraite peut étendre une autre classe Java et implémenter plusieurs interfaces Java. peut étendre une autre classe Java et implémenter plusieurs interfaces Java.
Une classe Java peut implémenter plusieurs interfaces mais ne peut étendre qu'une seule classe abstraite. une classe abstraite.
Cependant, l'interviewer n'était pas satisfait et m'a dit que cette description représentait "des connaissances livresques" ;.
Il m'a demandé une réponse plus pratique, expliquant quand je choisirais une classe abstraite plutôt qu'une interface, en utilisant des exemples pratiques.
Où ai-je fait fausse route ?
Rien n'est parfait dans ce monde. Ils s'attendaient peut-être à une approche plus pratique.
Mais après votre explication, vous pourriez ajouter ces lignes avec une approche légèrement différente.
Les interfaces sont des règles (règles parce que vous devez leur donner une mise en œuvre que vous ne pouvez pas ignorer ou éviter, de sorte qu’elles sont imposées comme des règles) qui fonctionnent comme un document de compréhension commune entre les différentes équipes de développement de logiciels.
Les interfaces donnent une idée de ce qui doit être fait mais pas de la manière dont cela sera fait. La mise en œuvre dépend donc entièrement du développeur qui suit les règles données (c'est-à-dire la signature donnée des méthodes).
Les classes abstraites peuvent contenir des déclarations abstraites, des implémentations concrètes, ou les deux.
Les déclarations abstraites sont comme des règles à suivre et les implémentations concrètes sont comme des directives (vous pouvez les utiliser telles quelles ou les ignorer en les surchargeant et en leur donnant votre propre implémentation).
De plus, les méthodes ayant la même signature et dont le comportement peut changer dans un contexte différent sont fournies dans les déclarations d'interface comme des règles à mettre en œuvre en conséquence dans des contextes différents.
**Java 8 permet de définir des méthodes par défaut et statiques dans les interfaces.
public interface SomeInterfaceOne {
void usualAbstractMethod(String inputString);
default void defaultMethod(String inputString){
System.out.println("Inside SomeInterfaceOne defaultMethod::"+inputString);
}
}
Maintenant, lorsqu'une classe implémente SomeInterface, il n'est pas obligatoire de fournir une implémentation pour les méthodes par défaut de l'interface.
Si nous avons une autre interface avec les méthodes suivantes :
public interface SomeInterfaceTwo {
void usualAbstractMethod(String inputString);
default void defaultMethod(String inputString){
System.out.println("Inside SomeInterfaceTwo defaultMethod::"+inputString);
}
}
Java n'autorise pas l'extension de plusieurs classes car cela entraîne le "problème du diamant " où le compilateur n'est pas capable de décider quelle méthode de la superclasse utiliser. Avec les méthodes par défaut, le problème du diamant se posera également pour les interfaces. Car si une classe implémente à la fois
SomeInterfaceOne and SomeInterfaceTwo
et n'implémente pas la méthode commune par défaut, le compilateur ne peut pas décider laquelle choisir. Pour éviter ce problème, en java 8, il est obligatoire d'implémenter les méthodes communes par défaut des différentes interfaces. Si une classe implémente les deux interfaces ci-dessus, elle doit fournir une implémentation de la méthode defaultMethod(), sinon le compilateur lancera une erreur de compilation.
Votre explication semble correcte, mais vous avez peut-être l'impression d'avoir tout lu dans un manuel... :-/
Ce qui me préoccupe le plus, c'est la solidité de votre exemple. Avez-vous pris la peine d'inclure presque toutes les différences entre les abstractions et les interfaces ?
Personnellement, je suggérerais ce lien : http://mindprod.com/jgloss/interfacevsabstract.html#TABLE
pour une liste exhaustive des différences..
J'espère que cela vous aidera, ainsi que tous les autres lecteurs, dans leurs futurs entretiens.
Une interface est un "contrat" dans lequel la classe qui implémente le contrat promet d'implémenter les méthodes. Un exemple où j'ai dû écrire une interface au lieu d'une classe est celui de la mise à niveau d'un jeu de la 2D à la 3D. J'ai dû créer une interface pour partager les classes entre la version 2D et la version 3D du jeu.
package adventure;
import java.awt.*;
public interface Playable {
public void playSound(String s);
public Image loadPicture(String s);
}
Je peux alors implémenter les méthodes en fonction de l'environnement, tout en étant capable d'appeler ces méthodes à partir d'un objet qui ne sait pas quelle version du jeu est en train de charger.
classe publique Adventure extends JFrame implements Playable
classe publique Dungeon3D extends SimpleApplication implements Playable
.
public class Main extends SimpleApplication implements AnimEventListener, ActionListener, Playable
Typiquement, dans le monde du jeu, le monde peut être une classe abstraite qui exécute des méthodes sur le jeu :
public abstract class World...
public Playable owner;
public Playable getOwner() {
return owner;
}
public void setOwner(Playable owner) {
this.owner = owner;
}