Récemment, dans une interview, on m'a posé une question très générale "Qu'est-ce qui est abstrait en Java"? J'ai donné la définition, suivie d'une autre question sur l'abstrait, quelle est la méthode abstraite et la différence entre méthode abstraite et méthode concrète, etc Puis, enfin, l'intervieweur a demandé à donner un exemple en temps réel quand je devrais utiliser ou définir une classe comme abstraite.J'ai été dérouté.J'ai donné un exemple mais il n'a pas été convaincu.
Je l'ai googlé mais je n'ai trouvé aucune solution réelle.
Donc, quelqu'un peut-il me donner un exemple en temps réel, c'est-à-dire lorsqu'il a défini une classe comme abstraite dans son projet et pourquoi?
Merci.
Un bon exemple de temps réel trouvé depuis ici : -
Un exemple concret de classe abstraite serait une classe appelée Animal. Vous voyez beaucoup d'animaux dans la vie réelle, mais il n'y a que des sortes de animaux. C'est-à-dire que vous ne regardez jamais quelque chose de violet et de velu et que vous dites "c'est un animal et il n'y a pas de manière plus spécifique de le définir" . Au lieu de cela, vous voyez un chien, un chat ou un cochon… tous des animaux. Le fait est que que vous ne pouvez jamais voir un animal se promener qui n'est pas plus spécifiquement quelque chose d'autre (canard, cochon, etc.). L'animal est le Classe abstraite et Canard/Cochon/Chat sont toutes les classes qui en dérivent classe de base. Les animaux peuvent fournir une fonction appelée "Âge" qui ajoute 1 année de vie aux animaux. Il pourrait également fournir une méthode abstraite appelé "IsDead" qui, lorsqu'il est appelé, vous dira si l'animal a décédés. IsDead étant abstrait, chaque animal doit le mettre en œuvre. Donc, un Cat pourrait décider qu'il est mort après avoir atteint l'âge de 14 ans, mais un Le canard pourrait décider qu'il meurt après 5 ans. La classe abstraite Animal fournit la fonction Age à toutes les classes qui en dérivent, mais chacune de ces classes doit implémenter IsDead par elles-mêmes.
Une entreprise exemple :
J'ai un moteur de persistance qui fonctionnera contre n'importe quel fournisseur de données (XML, ASCII (délimité et de longueur fixe), différentes sources JDBC (Oracle, SQL, ODBC, etc.) J'ai créé une classe abstraite de base pour fournir à Des fonctionnalités communes dans cette persistance, mais instanciez le "Port" approprié (sous-classe) approprié pour la persistance de mes objets (cela facilite beaucoup le développement de nouveaux "Ports", étant donné que la majeure partie du travail est effectuée dans les superclasses; en particulier les divers JDBC, puisque je ne fais pas que persister, mais d’autres choses [comme la génération de tables], j’ai le devoir de fournir les différentes différences pour chaque base de données). Les meilleurs exemples d’interfaces sont les collections. peut travailler avec un Java.util.List sans se soucier de la façon dont il est implémenté; avoir la liste en tant que classe abstraite n’a aucun sens car il existe des différences fondamentales dans le fonctionnement d’unArrayList par opposition à un LinkedList . De même, Map and Set. Et si je travaille uniquement avec un groupe d'objets Et que je ne me soucie pas de savoir s'il s'agit d'une liste, d'une carte ou d'un ensemble, je un juste utiliser le Interface de collection.
Ici, quelque chose à propos de la classe abstraite ...
Exemple en temps réel--
Si vous souhaitez créer une nouvelle voiture (WagonX) dans laquelle toutes les propriétés d'une autre voiture sont incluses, telles que la couleur, la taille, le moteur, etc., et que vous souhaitez ajouter d'autres fonctionnalités telles que le modèle, baseEngine dans votre voiture. classe WagonX où vous utilisez toutes les fonctionnalités prédéfinies de manière abstraite et les autres fonctionnalités sont concrètes et définies par vous.
Une autre sous-classe qui étend la classe abstraite WagonX. Par défaut, elle accède également aux méthodes abstraites instanciées dans la classe abstraite. Les sous-classes accèdent également aux méthodes concrètes en créant l'objet de la sous-classe.
Pour que le code soit réutilisable, les développeurs utilisent principalement des classes abstraites.
abstract class WagonX
{
public abstract void model();
public abstract void color();
public static void baseEngine()
{
// your logic here
}
public static void size()
{
// logic here
}
}
class Car extends WagonX
{
public void model()
{
// logic here
}
public void color()
{
// logic here
}
}
Le meilleur exemple de classe abstraite est GenericServlet
. GenericServlet
est la classe parente de HttpServlet
. C'est une classe abstraite.
Lors de l'héritage de 'GenericServlet' dans une classe de servlet personnalisée, la méthode service()
doit être remplacée.
Vous devriez pouvoir en citer au moins un extrait du JDK lui-même. Regardez dans le package Java.util.collections
. Il existe plusieurs classes abstraites. Vous devez parfaitement comprendre l'interface, l'abstrait et le concret pour Map
et pourquoi Joshua Bloch l'a écrit de cette façon.
J'utilise souvent des classes abstraites en conjonction avec Template method pattern .
Dans la classe abstraite principale, j’ai écrit le squelette de l’algorithme principal et créé des méthodes abstraites sous la forme de points d’accrochage permettant aux sous-classes d’effectuer une implémentation spécifique; J'utilisais souvent lors de l'écriture d'un analyseur de données (ou d'un processeur) devant lire des données d'un endroit différent (fichier, base de données ou d'autres sources), ayant une étape de traitement similaire (peut-être de petites différences) et une sortie différente.
Ce modèle ressemble à Modèle stratégique mais il vous donne moins de précision et peut dégrader en un code difficile à maintenir si le code principal se développe trop ou si des exceptions par rapport au flux principal sont requises (ces considérations sont venues de mon expérience).
Juste un petit exemple:
abstract class MainProcess {
public static class Metrics {
int skipped;
int processed;
int stored;
int error;
}
private Metrics metrics;
protected abstract Iterator<Item> readObjectsFromSource();
protected abstract boolean storeItem(Item item);
protected Item processItem(Item item) {
/* do something on item and return it to store, or null to skip */
return item;
}
public Metrics getMetrics() {
return metrics;
}
/* Main method */
final public void process() {
this.metrics = new Metrics();
Iterator<Item> items = readObjectsFromSource();
for(Item item : items) {
metrics.processed++;
item = processItem(item);
if(null != item) {
if(storeItem(item))
metrics.stored++;
else
metrics.error++;
}
else {
metrics.skipped++;
}
}
}
}
class ProcessFromDatabase extends MainProcess {
ProcessFromDatabase(String query) {
this.query = query;
}
protected Iterator<Item> readObjectsFromSource() {
return sessionFactory.getCurrentSession().query(query).list();
}
protected boolean storeItem(Item item) {
return sessionFactory.getCurrentSession().saveOrUpdate(item);
}
}
Ici un autre exemple.