Exam on Object-Oriented Programming

Exercice 1 - Questions à Choix Multiples (QCM) Question 1 - Les constructeurs Réponses correctes : b) et e) b) est une méthode sans type de retour : C'est exact. Un constructeur se distingue des autres méthodes en Java car il ne déclare aucun type de retour, pas même void .

D'après le document Exam on Object-Oriented Programming

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

Exam on Object-Oriented Programming

Document source

Exam on Object-Oriented Programming

Programming · PDF · 4 pages · 2016

Afficher l'aperçu du document

Consulter le document original →

Exercice 1 - Questions à Choix Multiples (QCM)

Question 1 - Les constructeurs

Réponses correctes : b) et e)

  • b) est une méthode sans type de retour : C'est exact. Un constructeur se distingue des autres méthodes en Java car il ne déclare aucun type de retour, pas même void.
  • e) est utilisé pour instancier l'objet à sa création : Le constructeur est en effet la méthode appelée immédiatement après l'allocation mémoire (via le mot-clé new) pour initialiser l'état de l'objet.
  • Pourquoi les autres sont fausses : Un constructeur peut tout à fait posséder des paramètres (ce qui invalide a). Il est exécuté à chaque création d'un nouvel objet, et non pas une seule fois au démarrage (ce qui invalide c). Enfin, la déclaration en mémoire est gérée par le mot-clé new et le système, le constructeur s'occupant de l'initialisation (ce qui nuance d, bien que souvent confondu).

Question 2 - Héritage entre classes

Réponses correctes : a) et c)

  • a) les attributs publics de A sont accessibles directement dans la classe B : Vrai. Le modificateur public garantit l'accessibilité dans toutes les classes, y compris les sous-classes.
  • c) les méthodes publiques de A sont accessibles dans B : Vrai, pour la même raison que les attributs publics. L'héritage permet à B d'utiliser les comportements publics de A.
  • Pourquoi les autres sont fausses : Les attributs privés (b) restent strictement confinés à la classe A (il faut utiliser des accesseurs/mutateurs). Il n'y a aucune obligation de redéfinir les méthodes (d) à moins qu'elles ne soient abstraites. Enfin, on a tout à fait le droit de redéfinir (surcoucher) les méthodes héritées (e).

Question 3 - Les attributs statiques

Réponse correcte : b)

  • b) variable de classe : Un attribut déclaré avec le mot-clé static appartient à la classe elle-même et non à une instance particulière. Sa valeur est partagée par tous les objets créés à partir de cette classe. Les variables d'instance (a) ne sont pas statiques, et les variables d'interface (c) ou locales (d) répondent à d'autres contextes.

Question 4 - Nature d'un objet

Réponses correctes : b), d) et e)

  • b) doit avoir obligatoirement un type : Tout objet en Java possède un type, qui correspond à la classe à partir de laquelle il a été instancié.
  • d) est une instanciation d'une classe : C'est la définition même d'un objet en programmation orientée objet.
  • e) est obligatoirement créé à partir d'une classe : La classe sert de plan de construction pour l'objet.
  • Pourquoi les autres sont fausses : Bien qu'un objet possède une référence en mémoire (a est une formulation ambiguë), il n'est pas qu'une simple variable. Un objet encapsule des variables (qui peuvent être des objets ou des types primitifs) et des méthodes, il n'est pas limité à un ensemble de variables primitives définies dans Object (c).

Question 5 - Les classes abstraites

Réponses correctes : a), c) et e)

  • a) est une classe qui est obligatoirement déclarée avec le mot clef « abstract » : C'est la syntaxe requise en Java pour définir une classe abstraite.
  • c) peut ne pas contenir des méthodes abstraites si elle est déclarée avec le mot clef « abstract » : C'est exact, une classe abstraite peut ne contenir que des méthodes concrètes. Le fait de la rendre abstraite empêche simplement son instanciation directe.
  • e) Peut être utilisé comme « type » d'objets lors de leur déclaration : Le polymorphisme permet d'utiliser une classe abstraite comme type de référence (ex: MaClasseAbstraite obj = new SousClasseConcrete();).
  • Pourquoi les autres sont fausses : Elle ne doit pas obligatoirement contenir des méthodes abstraites (b). Surtout, une classe abstraite ne peut jamais être instanciée directement avec new (d).

Exercice 2 - Application de location immobilière

Note sur l'énoncé : Le schéma UML de la classe Immobilier extrait du sujet présente une duplication de ses attributs (Numero, Ville, Surface, Etat, Proprietaire apparaissent deux fois dans le texte extrait). La correction se basera sur la liste logique et unique de ces attributs.

Question 1 - Attributs de la classe Personne

Nous déclarons les attributs en respectant la visibilité private pour garantir l'encapsulation.

public class Personne {
    private String nom;
    private String contact;
    
    // La suite du code de la classe sera développée dans les questions suivantes.
}

Question 2 - Constructeur avec paramètres

Le constructeur porte le même nom que la classe et initialise les attributs avec les valeurs passées en paramètres. On utilise this pour lever l'ambiguïté entre les paramètres et les attributs de la classe.

    public Personne(String nom, String contact) {
        this.nom = nom;
        this.contact = contact;
    }

Question 3 - Constructeur par défaut

Le constructeur par défaut reste-t-il disponible ? Non. En Java, le compilateur fournit un constructeur par défaut (sans paramètres) uniquement si le programmeur ne définit aucun constructeur. Puisque nous avons défini un constructeur avec paramètres à la question 2, le constructeur par défaut implicite disparaît.

Pour le rendre à nouveau disponible, il faut le redéfinir explicitement :

    public Personne() {
        this.nom = "";
        this.contact = "";
    }

Question 4 - Surcharge de méthodes

Principe : Ce principe s'appelle la surcharge (ou overloading en anglais). Conditions nécessaires : Pour définir deux méthodes (ou constructeurs) ayant le même nom dans la même classe, il faut que leurs signatures soient différentes. Cela signifie que la liste de leurs paramètres doit différer par :

  1. Le nombre de paramètres.
  2. Le type des paramètres.
  3. L'ordre des types de paramètres. (Note : le type de retour seul ne suffit pas à différencier deux méthodes surchargées).

Question 5 - Méthode AfficherDetail()

Cette méthode affiche l'état actuel de l'objet sur la sortie standard.

    public void afficherDetail() {
        System.out.println("Nom : " + this.nom);
        System.out.println("Contact : " + this.contact);
    }

Question 6 - Méthode SaisirDetailPersonne()

Pour donner la main à l'utilisateur, nous importons et utilisons la classe java.util.Scanner. L'énoncé demande une méthode d'instance qui met à jour les attributs de l'objet courant.

    import java.util.Scanner;

    public void saisirDetailPersonne() {
        Scanner sc = new Scanner(System.in);
        System.out.print("Veuillez saisir le nom : ");
        this.nom = sc.nextLine();
        System.out.print("Veuillez saisir le contact : ");
        this.contact = sc.nextLine();
        // Attention: la fermeture du scanner (sc.close()) ici fermerait System.in 
        // pour tout le reste du programme, on évite donc de le fermer dans cette méthode.
    }

Question 7 - Accesseurs (get et set)

Les accesseurs permettent de lire (get) et de modifier (set) les variables privées de manière contrôlée.

    // Accesseurs pour 'nom'
    public String getNom() {
        return this.nom;
    }

    public void setNom(String nom) {
        this.nom = nom;
    }

    // Accesseurs pour 'contact'
    public String getContact() {
        return this.contact;
    }

    public void setContact(String contact) {
        this.contact = contact;
    }

Question 8 - Obligation des accesseurs

Sont-ils obligatoires ? Non, techniquement parlant, le compilateur Java n'oblige pas à écrire des accesseurs. Cependant, ils sont indispensables dans le cadre de l'encapsulation orientée objet si les attributs sont déclarés private (comme demandé à la question 1) et qu'ils doivent être consultés ou modifiés par d'autres classes de l'application. Sans eux, le reste du programme ne pourrait ni connaître le nom du propriétaire, ni le modifier après la création de l'objet.

Question 9 - Attributs de la classe Immobilier

Pour gérer un numéro "séquentiel et attribué automatiquement", il est nécessaire d'introduire une variable de classe statique (ex: compteur) qui gardera en mémoire le dernier numéro attribué.

public class Immobilier {
    private static int compteur = 1; // Attribut de classe pour l'auto-incrémentation
    
    private int numero;
    private String ville;
    private int surface;
    private boolean etat; // oui=libre (true), non=loué (false)
    private Personne proprietaire;
    
    // Suite du code...
}

Question 10 - Constructeur de la classe Immobilier

Le constructeur initialise un bien "vide" et gère l'incrémentation automatique du numéro.

    public Immobilier() {
        // Attribution du numéro séquentiel et incrémentation du compteur
        this.numero = compteur++;
        
        // Initialisation des autres attributs aux valeurs par défaut demandées
        this.ville = null;
        this.surface = 0;
        this.etat = false;
        this.proprietaire = null;
    }

Question 11 - Méthode AfficherImmo() de la classe Immobilier

Cette méthode affiche les caractéristiques générales du bien. On prendra soin d'appeler la méthode d'affichage du propriétaire s'il existe.

    public void afficherImmo() {
        System.out.println("--- Immobilier N°" + this.numero + " ---");
        System.out.println("Ville : " + this.ville);
        System.out.println("Surface : " + this.surface + " m2");
        System.out.println("Etat : " + (this.etat ? "Libre" : "Loué"));
        
        if (this.proprietaire != null) {
            System.out.println("Détails du propriétaire :");
            this.proprietaire.afficherDetail();
        } else {
            System.out.println("Aucun propriétaire assigné.");
        }
    }

Question 12 - Redéfinition de AfficherImmo() dans Appartement et Maison

Ces classes héritent de Immobilier (mot-clé extends). La redéfinition utilise super.afficherImmo() pour appeler le comportement de la classe mère avant d'afficher les informations spécifiques à l'enfant.

Pour la classe Appartement :

public class Appartement extends Immobilier {
    private String residence;
    private int etage;
    private int numApp;

    // Constructeurs et autres méthodes ignorés pour la concision...

    @Override
    public void afficherImmo() {
        super.afficherImmo(); // Appel de la méthode de la classe mère
        System.out.println("Type : Appartement");
        System.out.println("Résidence : " + this.residence);
        System.out.println("Etage : " + this.etage);
        System.out.println("N° Appartement : " + this.numApp);
    }
}

Pour la classe Maison :

public class Maison extends Immobilier {
    private String rue;
    private int numMaison;

    // Constructeurs et autres méthodes ignorés pour la concision...

    @Override
    public void afficherImmo() {
        super.afficherImmo(); // Appel de la méthode de la classe mère
        System.out.println("Type : Maison");
        System.out.println("Rue : " + this.rue);
        System.out.println("N° Maison : " + this.numMaison);
    }
}

Question 13 - Classe Application et méthode main()

L'énoncé stipule que les méthodes saisirImmo() sont déjà définies dans toutes les classes. Le but ici est de démontrer l'utilisation du polymorphisme : un tableau de type Immobilier peut contenir des instances de Maison ou d'Appartement, et Java appellera automatiquement la bonne méthode redéfinie selon la nature réelle de l'objet lors de l'exécution (liaison dynamique).

import java.util.Scanner;

public class Application {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        // 1) Déclarer un tableau « Tab » de 10 Immobiliers.
        Immobilier[] tab = new Immobilier[10];

        // 2) Pour chaque Immobilier dans le tableau :
        for (int i = 0; i < tab.length; i++) {
            System.out.println("\n--- Saisie de l'immobilier " + (i+1) + " sur 10 ---");
            
            // 2.1) Demander le type à l'utilisateur
            System.out.print("Voulez-vous ajouter une Maison (M) ou un Appartement (A) ? : ");
            String choix = sc.nextLine();

            // 2.2) Création de l'objet selon le choix
            if (choix.equalsIgnoreCase("M")) {
                tab[i] = new Maison();
            } else if (choix.equalsIgnoreCase("A")) {
                tab[i] = new Appartement();
            } else {
                System.out.println("Choix invalide, un Appartement sera créé par défaut.");
                tab[i] = new Appartement();
            }

            // 2.3) Saisir les informations relatives à l'objet
            // Grâce au polymorphisme, c'est la méthode saisirImmo() de la sous-classe 
            // (Maison ou Appartement) qui sera exécutée.
            tab[i].saisirImmo();
        }

        System.out.println("\n=================================");
        System.out.println("AFFICHAGE DE TOUS LES IMMOBILIERS");
        System.out.println("=================================");

        // 3) Pour chaque Immobilier dans le tableau : afficher les informations
        for (int i = 0; i < tab.length; i++) {
            // Polymorphisme : appelle la méthode afficherImmo() spécifique à l'objet réel
            tab[i].afficherImmo();
            System.out.println("---------------------------------");
        }
        
        sc.close();
    }
}

Question 14 - Interface OperationImmobilier et implémentation

Une interface en Java déclare des signatures de méthodes (implicitement publiques et abstraites) que les classes qui l'implémentent s'engagent à définir.

// Code de l'interface
public interface OperationImmobilier {
    void saisirImmo();
    void afficherImmo();
}

// Entête de la classe Immobilier qui implémente l'interface
public class Immobilier implements OperationImmobilier {
    // Le contenu de la classe reste le même que vu précédemment
    // Elle doit fournir le code des méthodes saisirImmo() et afficherImmo().
}

Méthode

Face à un examen de Programmation Orientée Objet, la difficulté réside souvent dans la bonne gestion du temps et l'imbrication des concepts :

  1. Lisez l'intégralité du diagramme de classes ou des spécifications avant de coder. Dans cet examen, on voit que l'attribut Numero est séquentiel (auto). Cela indique immédiatement qu'il faudra utiliser un modificateur static pour un compteur global, une notion classique des examens qu'il faut repérer dès le brouillon.
  2. Soignez l'encapsulation. Mettez systématiquement vos attributs en private. Le barème pénalise souvent un étudiant qui oublie ce modificateur, car l'encapsulation est le pilier de l'approche objet.
  3. Comprenez le polymorphisme. La question 13 est le cœur d'un tel devoir. On ne vous demande pas de faire des "if" lors de l'affichage pour vérifier le type de la classe. L'intérêt d'un tableau d'objets parents (Immobilier[]) est de pouvoir appeler tab[i].afficherImmo() en laissant la machine virtuelle Java déterminer si elle doit exécuter le code de la classe Maison ou de la classe Appartement.
  4. Attention à la gestion des entrées clavier. Lorsque vous utilisez la classe Scanner, soyez vigilant : si vous fermez le flux standard (sc.close()) dans une méthode comme SaisirDetailPersonne(), vous empêcherez toute lecture ultérieure dans votre application (notamment dans la boucle de la méthode main). Pensez à l'architecture globale de vos entrées.

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