Devoir surveillé en Java et JEE

Ce devoir surveillé porte sur le langage Java et la programmation orientée objet dans le contexte JEE. Il évalue les connaissances théoriques sur les concepts fondamentaux de la POO ainsi que la capacité à modéliser un système complexe en respectant les bonnes pratiques de conception orientée objet.

D'après le document Devoir surveillé en Java et JEE

Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.

Document source

Devoir surveillé en Java et JEE

Programming · ENIT · PDF · 1 pages · 2015

Afficher l'aperçu du document

Consulter le document original →

Ce devoir surveillé porte sur le langage Java et la programmation orientée objet dans le contexte JEE. Il évalue les connaissances théoriques sur les concepts fondamentaux de la POO ainsi que la capacité à modéliser un système complexe en respectant les bonnes pratiques de conception orientée objet.

Première partie

Q1 : Différence entre une classe abstraite et une interface, et leurs utilités

Il est demandé d'expliquer brièvement la différence entre une classe abstraite et une interface, ainsi que leurs utilités.

Une classe abstraite est une classe qui ne peut pas être instanciée directement. Elle peut contenir des attributs, des méthodes concrètes (avec une implémentation) et des méthodes abstraites (sans implémentation). Elle sert de base commune à plusieurs classes dérivées qui héritent de ses caractéristiques et doivent implémenter ses méthodes abstraites.

Une interface est un contrat qui ne contient que des méthodes abstraites (sans implémentation) et des constantes. Elle définit un ensemble de comportements que les classes implémentant cette interface doivent obligatoirement fournir. Une classe peut implémenter plusieurs interfaces, ce qui permet de contourner la limitation de l'héritage simple en Java.

Utilités :

  • La classe abstraite est utilisée pour partager du code commun et définir une structure partagée entre classes proches.
  • L'interface est utilisée pour garantir qu'une classe respecte un certain comportement, indépendamment de sa position dans la hiérarchie des classes.

Réponse finale : La classe abstraite permet de factoriser du code commun et de définir des méthodes abstraites à implémenter, tandis que l'interface définit un contrat strict de méthodes à implémenter sans fournir de code. La classe abstraite sert à structurer une hiérarchie de classes, l'interface à garantir des comportements communs indépendamment de l'héritage.

Q2 : Différence entre surcharge et redéfinition, et règles associées

Il faut expliquer brièvement la différence entre la surcharge (overloading) et la redéfinition (overriding) ainsi que les règles qui les régissent.

Surcharge (overloading) : C'est la définition de plusieurs méthodes dans une même classe portant le même nom mais avec des signatures différentes (différents types ou nombre de paramètres). Elle permet d'avoir plusieurs comportements selon les arguments passés.

Redéfinition (overriding) : C'est la modification de l'implémentation d'une méthode héritée d'une superclasse dans une sous-classe. La méthode redéfinie doit avoir la même signature que celle de la superclasse.

Règles :

  • Pour la surcharge : les méthodes doivent différer par le nombre ou le type des paramètres.
  • Pour la redéfinition : la méthode doit avoir la même signature (même nom, même paramètres) que dans la superclasse.
  • La redéfinition doit respecter la visibilité (la méthode redéfinie ne peut pas avoir une visibilité plus restrictive).
  • La redéfinition peut modifier le comportement mais pas la signature.

Réponse finale : La surcharge consiste à définir plusieurs méthodes du même nom avec des signatures différentes dans une même classe, tandis que la redéfinition consiste à modifier l'implémentation d'une méthode héritée en conservant sa signature. Les règles imposent des signatures différentes pour la surcharge et une signature identique pour la redéfinition, avec respect des niveaux de visibilité.

Q3 : Concept de polymorphisme et son utilité

Il s'agit d'expliquer brièvement ce qu'est le polymorphisme et à quoi il sert.

Le polymorphisme est la capacité d'un objet à prendre plusieurs formes, c'est-à-dire qu'une variable de type superclasse peut référencer des objets de différentes sous-classes. Cela permet d'appeler des méthodes sur des objets sans connaître leur type exact à la compilation, la méthode appelée étant celle correspondant au type réel de l'objet (liaison dynamique).

Utilité : Le polymorphisme permet d'écrire du code générique et extensible, facilitant la maintenance et l'évolution du logiciel. Il permet notamment d'utiliser des collections d'objets hétérogènes partageant une interface commune et d'appeler leurs méthodes spécifiques sans tests de type.

Réponse finale : Le polymorphisme permet à une même interface d'être utilisée pour des objets de différentes classes, facilitant la flexibilité et l'extensibilité du code en permettant d'appeler des méthodes spécifiques selon le type réel de l'objet.

Deuxième partie

Modélisation du parc automobile

Il faut modéliser une hiérarchie de classes représentant différents types de véhicules (petits bus, camions citernes, camions bâchés) en respectant les principes de la programmation orientée objet, avec des attributs privés, des constructeurs paramétrés, et des méthodes adaptées.

Analyse du problème :

  • Chaque véhicule possède une immatriculation unique et un poids à vide (fixe selon le type).
  • Certains véhicules transportent une charge maximale (camions citernes et bâchés).
  • Chaque véhicule doit pouvoir calculer sa vitesse maximale avec la méthode int calculerVitesseMaximale().
  • Certains véhicules (petits bus et autres futurs) peuvent être loués et doivent implémenter la méthode facturer(int d) qui retourne le prix pour une distance d, calculé à partir du temps de trajet basé sur la vitesse maximale et un tarif horaire de 200 dt/h.

Étape 1 : Hiérarchie des classes

On commence par définir une classe abstraite Vehicule qui contient les attributs communs :

  • private String immatriculation;
  • private double poidsAVide;

Cette classe aura un constructeur paramétré et une méthode abstraite int calculerVitesseMaximale() que les sous-classes doivent implémenter.

Ensuite, on distingue deux catégories :

  • Les véhicules sans charge transportable : PetitBus
  • Les véhicules avec charge transportable : une classe abstraite Camion qui hérite de Vehicule et ajoute :
  • private double chargeMax;
  • private double chargeActuelle;

avec un constructeur paramétré et la méthode calculerVitesseMaximale() implémentée selon les règles spécifiques.

Étape 2 : Classes concrètes

  • PetitBus : poids à vide = 4 tonnes, nombre de places (attribut privé), vitesse max fixe = 150 km/h.
  • CamionCiterne : poids à vide = 3 tonnes, charge max = 10 tonnes, vitesse max = 120 km/h si charge < 4 tonnes, sinon 90 km/h.
  • CamionBache : poids à vide = 4 tonnes, charge max = 20 tonnes, vitesse max = 110 km/h si charge < 3 tonnes, sinon 80 km/h.

Étape 3 : Interface pour véhicules louables

On définit une interface Louable avec la méthode double facturer(int d). Cette méthode calcule le prix en fonction de la distance parcourue et de la vitesse maximale :

Durée du trajet (en heures) = distance / vitesse maximale

Prix = durée × 200 dt

Seuls les petits bus et certains autres véhicules (non modélisés ici) implémentent cette interface.

Étape 4 : Classe LocationConvoi

Cette classe représente un ensemble de véhicules loués. Elle contient une collection de véhicules louables (par exemple une List<Louable>) et propose la méthode :

double calculerCoutLocation(int distance)

Cette méthode parcourt tous les véhicules du convoi, appelle leur méthode facturer(distance) et additionne les coûts pour retourner le coût total.

Étape 5 : Suggestions pour la classe Entreprise

Pour faciliter le développement d'une classe Entreprise regroupant une collection de véhicules, il faudrait :

  • Utiliser une collection générique (List ou Set) pour stocker les véhicules.
  • Implémenter la méthode equals() et hashCode() dans la classe Vehicule basée sur l'immatriculation, pour permettre la recherche et la suppression efficaces.
  • Implémenter l'interface Comparable ou fournir un Comparator pour trier les véhicules par vitesse maximale.
  • Fournir des méthodes de recherche par immatriculation, de tri par vitesse maximale, et de suppression dans la classe Entreprise.

Méthode

Ce devoir récompense une bonne compréhension des concepts fondamentaux de la programmation orientée objet : abstraction, héritage, encapsulation, polymorphisme et interfaces. Il valorise également la capacité à modéliser un système complexe en respectant les principes de conception robustes et extensibles.

Les erreurs à éviter sont :

  • Ne pas utiliser les modificateurs d'accès appropriés (il faut privilégier private pour les attributs).
  • Ne pas respecter la signature des méthodes abstraites ou des interfaces.
  • Confondre surcharge et redéfinition.
  • Ne pas factoriser le code commun dans une classe abstraite.
  • Ne pas prévoir l'extensibilité, par exemple en durcissant trop la hiérarchie ou en ne respectant pas le principe d'ouverture/fermeture.
  • Oublier d'implémenter les méthodes nécessaires pour la gestion des collections (equals, hashCode, comparators).

Enfin, il est important de montrer clairement les étapes de raisonnement, de définir les classes et interfaces avec leurs attributs et méthodes, et de justifier les choix de conception.

Partager

Commentaires

Aucun commentaire pour le moment. Posez la première question.

Les commentaires sont relus avant publication. Votre e-mail n'est jamais affiché.

← Toutes les révisions