Devoir Surveillé de Conception orientée objet et programmation Java

Ce devoir surveillé porte sur la conception orientée objet et la programmation Java. Il évalue les compétences en compréhension de code Java, en héritage, en encapsulation, ainsi qu’en conception et implémentation de classes selon un cahier des charges précis, incluant la gestion d’exceptions. QCM / QUESTIONS DE COUR QUESTION 1 Combien d’instances de la classe A crée le code suivant ?

D'après le document Devoir Surveillé de Conception orientée objet et programmation Java

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

Document source

Devoir Surveillé de Conception orientée objet et programmation Java

Programming, Object-Oriented Design, Java · PDF · 4 pages · 2018

Afficher l'aperçu du document

Consulter le document original →

Ce devoir surveillé porte sur la conception orientée objet et la programmation Java. Il évalue les compétences en compréhension de code Java, en héritage, en encapsulation, ainsi qu’en conception et implémentation de classes selon un cahier des charges précis, incluant la gestion d’exceptions.

QCM / QUESTIONS DE COUR

QUESTION 1

Combien d’instances de la classe A crée le code suivant ?

A x,u,v;
x=new A();
A y=x;
A z=new A();

Analyse :

  • La déclaration A x,u,v; ne crée pas d’instances, elle déclare simplement des références.
  • x = new A(); crée une instance de A.
  • A y = x; ne crée pas d’instance, y référence la même instance que x.
  • A z = new A(); crée une nouvelle instance de A.

Au total, deux instances de la classe A sont créées.

Réponse : D. Deux

QUESTION 2

Quel est le résultat de l'exécution du programme suivant ?

public class ClasseA {
  public void affiche() {
    System.out.println("je suis un objet de ClasseA");
  }
}
class ClasseB extends ClasseA {
  public void affiche() {
    super.affiche();
    System.out.println("je suis un objet de ClasseB");
  }
}
public class ClasseTest {
  public void main(String[] args) {
    ClasseA b = new ClasseB();
    b.affiche();
  }
}

Analyse :

  • La variable b est de type ClasseA mais référence un objet de type ClasseB.
  • La méthode affiche() est appelée sur b. En Java, la méthode appelée est celle de l’objet réel (polymorphisme).
  • La méthode affiche() de ClasseB est donc exécutée.
  • Dans cette méthode, super.affiche() appelle la méthode affiche() de ClasseA, affichant "je suis un objet de ClasseA".
  • Ensuite, la ligne suivante affiche "je suis un objet de ClasseB".

Le résultat affiché est donc :

je suis un objet de ClasseA
je suis un objet de ClasseB

Réponse : Le programme affiche :

je suis un objet de ClasseA
je suis un objet de ClasseB

QUESTION 3

Choisissez la bonne ou les bonnes réponses :

  • A. Une classe peut implémenter plusieurs interfaces mais doit étendre une seule classe
  • B. Une classe peut implémenter plusieurs classes mais doit étendre une seule interface
  • C. Une classe peut implémenter plusieurs classes et peut étendre plusieurs interfaces
  • D. Une classe doit, impérativement, implémenter une seule interface et étendre une seule classe

Analyse :

  • En Java, une classe peut implémenter plusieurs interfaces.
  • Une classe ne peut pas implémenter une classe (ce n’est pas syntaxiquement correct).
  • Une classe ne peut étendre qu’une seule classe (héritage simple).
  • Elle peut implémenter zéro, une ou plusieurs interfaces.

Donc la bonne réponse est :

A. Une classe peut implémenter plusieurs interfaces mais doit étendre une seule classe

QUESTION 4

Qui peut accéder et modifier la variable name dans la classe suivante ?

package test;
public class Target {
  String name = "hello";
}

Analyse :

  • L’attribut name est déclaré sans modificateur d’accès, donc il a le niveau d’accès "package-private" (accessible uniquement dans le même paquetage).
  • Donc, seules les classes du paquetage test peuvent accéder et modifier name.
  • Ni les classes en dehors du paquetage, ni les classes héritant de Target en dehors du paquetage ne peuvent y accéder.

La bonne réponse est :

C. n’importe quelles classes dans le paquetage test

PROBLÈME

1ère Question

Développer la classe Citoyen avec les attributs, constructeurs, getters/setters, méthode equals et méthode toString.

Attributs :

  • int cin
  • String nom
  • String prenom

Constructeurs :

  • Constructeur par défaut (sans paramètres)
  • Constructeur paramétré (avec paramètres pour initialiser les attributs)

Getters et setters pour l’attribut cin (les autres sont supposés implémentés).

Méthode equals(Object obj) : deux citoyens sont égaux si leur nom et leur cin sont identiques.

Méthode toString() : affiche les caractéristiques du citoyen.

public class Citoyen {
  private int cin;
  private String nom;
  private String prenom;

  // Constructeur par défaut
  public Citoyen() {
    this.cin = 0;
    this.nom = "";
    this.prenom = "";
  }

  // Constructeur paramétré
  public Citoyen(int cin, String nom, String prenom) {
    this.cin = cin;
    this.nom = nom;
    this.prenom = prenom;
  }

  // Getter pour cin
  public int getCin() {
    return cin;
  }

  // Setter pour cin
  public void setCin(int cin) {
    this.cin = cin;
  }

  // equals : deux citoyens sont égaux si nom et cin sont identiques
  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    Citoyen other = (Citoyen) obj;
    return this.cin == other.cin && this.nom.equals(other.nom);
  }

  // toString : affiche les caractéristiques
  @Override
  public String toString() {
    return "Citoyen [cin=" + cin + ", nom=" + nom + ", prenom=" + prenom + "]";
  }
}

Réponse : La classe Citoyen est développée comme ci-dessus.

2ème Question

Implémenter la classe CitoyenExpatrie avec ses attributs, constructeur paramétré et méthode toString().

Analyse :

  • La classe CitoyenExpatrie hérite probablement de Citoyen (ceci est implicite dans le sujet).
  • Elle possède les attributs de Citoyen plus ses propres attributs (non précisés dans le texte, donc on suppose qu’il faut reprendre les attributs hérités).
  • Le constructeur paramétré doit initialiser tous les attributs.
  • La méthode toString() doit afficher les caractéristiques, en incluant celles héritées.

Implémentation possible :

public class CitoyenExpatrie extends Citoyen {
  private String paysResidence;

  // Constructeur paramétré
  public CitoyenExpatrie(int cin, String nom, String prenom, String paysResidence) {
    super(cin, nom, prenom);
    this.paysResidence = paysResidence;
  }

  // toString
  @Override
  public String toString() {
    return super.toString() + ", paysResidence=" + paysResidence;
  }
}

Remarque : Le sujet ne donne pas explicitement les attributs spécifiques à CitoyenExpatrie. Ici, on a ajouté un attribut plausible paysResidence pour illustrer la réponse. Si le sujet ne précise rien, on ne peut pas répondre plus précisément.

3ème Question

Développer la classe Pays avec :

  • Ses attributs
  • Le constructeur paramétré
  • La méthode void ajouterCitoyen(Citoyen c) (max 800 citoyens)
  • La méthode void afficherStat() qui affiche le nombre de citoyens locaux et expatriés
  • La méthode void supprimer(Citoyen c) qui supprime un citoyen
  • La méthode boolean estTunisien(Citoyen c) qui retourne true si le citoyen expatrié est tunisien, false sinon
  • La méthode afficherNbTunisiens() qui retourne le nombre de citoyens tunisiens expatriés et déclenche une exception NbMaxTunisiens si ce nombre dépasse 150
  • La classe d’exception NbMaxTunisiens

Développement détaillé :

Attributs

  • Un tableau ou un tableau dynamique (mais Collections interdites) de Citoyen pour stocker les citoyens.
  • Un entier pour compter le nombre actuel de citoyens.
public class Pays {
  private Citoyen[] citoyens;
  private int nbCitoyens;
  private final int MAX_CITOYENS = 800;

  // Constructeur paramétré
  public Pays() {
    citoyens = new Citoyen[MAX_CITOYENS];
    nbCitoyens = 0;
  }

  // Ajouter un citoyen
  public void ajouterCitoyen(Citoyen c) {
    if (nbCitoyens < MAX_CITOYENS) {
      citoyens[nbCitoyens] = c;
      nbCitoyens++;
    } else {
      System.out.println("Nombre maximum de citoyens atteint.");
    }
  }

  // Afficher statistiques
  public void afficherStat() {
    int nbLocaux = 0;
    int nbExpatries = 0;
    for (int i = 0; i < nbCitoyens; i++) {
      if (citoyens[i] instanceof CitoyenExpatrie) {
        nbExpatries++;
      } else {
        nbLocaux++;
      }
    }
    System.out.println("Nb Citoyens locaux= " + nbLocaux + " // Nb Citoyens expatries= " + nbExpatries);
  }

  // Supprimer un citoyen
  public void supprimer(Citoyen c) {
    for (int i = 0; i < nbCitoyens; i++) {
      if (citoyens[i].equals(c)) {
        // Décaler les éléments suivants vers la gauche
        for (int j = i; j < nbCitoyens - 1; j++) {
          citoyens[j] = citoyens[j + 1];
        }
        citoyens[nbCitoyens - 1] = null;
        nbCitoyens--;
        break;
      }
    }
  }

  // Vérifier si un citoyen expatrié est tunisien
  public boolean estTunisien(Citoyen c) {
    if (c instanceof CitoyenExpatrie) {
      CitoyenExpatrie ce = (CitoyenExpatrie) c;
      // Supposons que le pays d'origine est déterminé par le nom ou un attribut (non précisé)
      // Ici, on suppose que le nom "Tunisien" est dans le nom (hypothèse faute de précision)
      return ce.getNom().equalsIgnoreCase("Tunisien");
    }
    return false;
  }

  // Afficher nombre de tunisiens expatriés et déclencher exception si > 150
  public int afficherNbTunisiens() throws NbMaxTunisiens {
    int count = 0;
    for (int i = 0; i < nbCitoyens; i++) {
      if (citoyens[i] instanceof CitoyenExpatrie) {
        if (estTunisien(citoyens[i])) {
          count++;
        }
      }
    }
    if (count > 150) {
      throw new NbMaxTunisiens("Nombre maximum de tunisiens expatriés dépassé");
    }
    return count;
  }
}

Classe d’exception

public class NbMaxTunisiens extends Exception {
  public NbMaxTunisiens(String message) {
    super(message);
  }
}

Remarques :

  • La méthode estTunisien repose sur une hypothèse faute d’informations précises sur la façon d’identifier un citoyen tunisien.
  • La suppression décale les éléments du tableau pour éviter les trous.
  • La gestion du tableau respecte la contrainte d’interdire les Collections.

Réponse : La classe Pays et l’exception NbMaxTunisiens sont développées comme ci-dessus.

Méthode

Ce devoir récompense une bonne maîtrise des concepts fondamentaux de la programmation orientée objet en Java : compréhension des références et instances, héritage, polymorphisme, encapsulation, et gestion des exceptions.

Il est important de :

  • Analyser précisément le code donné, notamment la différence entre déclaration de variables et création d’instances.
  • Comprendre le polymorphisme et l’appel des méthodes dans une hiérarchie de classes.
  • Respecter les règles de syntaxe et de sémantique Java, notamment pour l’héritage et l’implémentation des interfaces.
  • Implémenter les classes en respectant les spécifications, notamment les constructeurs, méthodes equals et toString.
  • Gérer les collections d’objets sans utiliser les classes de la bibliothèque Java Collections, en manipulant des tableaux classiques.
  • Gérer les exceptions personnalisées pour contrôler des contraintes métier.
  • Présenter un code clair avec des étapes de raisonnement visibles, notamment pour les méthodes de suppression et de comptage.

Les erreurs à éviter sont :

  • Confondre déclaration et instanciation d’objets.
  • Ne pas utiliser le polymorphisme correctement (exemple : appeler une méthode sur une référence de type parent).
  • Ne pas respecter la signature des méthodes héritées ou surchargées.
  • Utiliser des Collections alors qu’elles sont interdites.
  • Ne pas gérer correctement les exceptions ou ne pas les déclarer.

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