US

Écriture de classes

Question 1

Écrivez une classe Item qui représente un article de magasin. Un article de magasin est identifié par un nom sous forme de chaine de caractères, un prix (flottant) et enfin un identifiant code-barre (entier de 13 chiffres). On peut également donner une description à l'objet mais c'est optionnel. Le code suivant vous montre la création de deux articles :

1 
2 
3 
4 
5 
public static void main (String[] args)
{
    Item i1 = new Item ("Vodka", "Une bouteille de Vodka", 5483918746738L, 75.5);
    Item i2 = new Item ("Filet de citron 200g", 5473664615361L, 3.25);
}

Ajoutez également deux méthodes getPrice a la classe :

public double getPrice();
public double getPrice (int q);

La première méthode renvoie simplement le prix de l'article, tandis que la seconde renvoie le prix pour q fois l'article en tenant compte du fait que si on commande plus de 10 fois un article, on reçoit 5% de réduction sur le prix total.

Solution

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
public class Item
{
    private String name, description;
    private long barcode;
    private double price;
 
    public Item (String name, String description, long barcode, double price)
    {
        this.name = name;
        this.description = description;
        this.barcode = barcode;
        this.price = price;
    }
 
    public Item (String name, long barcode, double price)
    {
        this (name, "", barcode, price);
    }
 
    public double getPrice()
    {
        return price;
    }
 
    public double getPrice (int q)
    {
        double tot = price * q;
        if (q >= 10)
        {
            tot = tot * 0.95;
        }
        return tot;
    }
}

La première chose à faire quand on écrit une classe est de définir les variables d'instance dont on va avoir besoin. Ici, c'est clair, il faut stocker le nom, la description, le code-barres et le prix. Il faut juste faire attention que le code-barres est sur 13 chiffres et il faut donc utiliser un long.

La deuxième question à se poser est quelles sont les possibilités qu'on veut offrir à l'utilisateur pour construire un objet de la classe, c'est-à-dire quels sont les constructeurs qu'on va définir. Ici, l'énoncé suggère bien deux constructeurs. On peut simplifier le second constructeur en se rappelant qu'on peut appeler un autre constructeur de la même classe en utilisant le mot réservé this.

La première méthode getPrice est un simple accesseur et pour la seconde, on commence par calculer le prix pour q article. Ensuite, si q est plus grand que 10, on décompte 5%.

Question 2

Écrivez une classe Person qui représente une personne. On construit un nouvel objet de la classe Person en fournissant son nom sous forme d'un String et sa date de naissance sous forme d'un objet de type GregorianCalendar.

De plus, la classe Person doit contenir deux méthodes dont voici les signatures :

public int getAge();
public Date getBirthdate();

Attention, les objets GregorianCalendar est muable, le listing suivant montre un exemple qui peut cause des effets de bords sur une classe Person mal implémentée.

1 
2 
3 
4 
5 
6 
7 
8 
9 
public static void main (String[] args)
{
    GregorianCalendar d = new GregorianCalendar (1984, Calendar.DECEMBER, 6);
    Person p = new Person ("Sébastien Combéfis", d);
 
    System.out.println (p.getBirthdate());
    d.add (Calendar.YEAR, -20);
    System.out.println (p.getBirthdate());
}

L'exécution du programme affiche à la console :

Thu Dec 06 00:00:00 CET 1984
Mon Dec 06 00:00:00 CET 1964

Tout d'un coup, la personne se retrouve née 20 ans plus tôt et est plus vieille de 20 ans ... On vous demande bien entendu d'éviter ce problème.

Solution

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
public class Person
{
    private String name;
    private GregorianCalendar birthdate;
 
    public Person (String name, GregorianCalendar birthdate)
    {
        this.name = name;
        this.birthdate = (GregorianCalendar) birthdate.clone();
    }
 
    public int getAge()
    {
        GregorianCalendar today = new GregorianCalendar();
        return today.get (Calendar.YEAR) - birthdate.get (Calendar.YEAR);
    }
 
    public Date getBirthdate()
    {
        return birthdate.getTime();
    }
}

On commence par les variables d'instances, on en définit 2 : une de type String pour le nom et une autre de type GregorianCalendar pour le jour de naissance.

Vient ensuite le constructeur qui va recopier ses paramètres dans les variables d'instance. Il faut juste se rappeler que les String sont immutables et on peut donc simplement copier la référence mais les GregorianCalendar sont mutables et il faut donc faire un copie en utilisant la méthode clone.

La méthode getBirthday est super simple et pour la méthode getAge, on simplifie les choses en ne prenant que l'année de naissance en compte dans le calcul de l'age.

Question 3

Écrivez une classe Rectangle qui représente un rectangle dans le plan. Un rectangle est caractérisé par une position dans le plan et par une longueur et une largeur. Votre classe doit posséder une méthode toString qui affiche les coordonnées et dimensions du rectangle et également une fonction fusion qui permet de faire la fusion entre deux rectangles.

Rectangles

La figure ci-dessus vous montre deux rectangles rouge et bleu et leur fusion en orange. La fusion de deux rectangles est donc le plus petit rectangle qui contienne les deux rectangles.

1 
2 
3 
4 
5 
6 
7 
8 
public static void main (String[] args)
{
    Rectangle r1 = new Rectangle (new Point (10, 10), 40, 30);
    Rectangle r2 = new Rectangle (new Point (-10, -10), 50, 30);
    System.out.println (r1);
    System.out.println (r2);
    System.out.println (r1.fusion (r2));
}

Le listing ci-dessus vous motnre un exemple d'utilisation de la classe Rectangle. Son exécution affiche à la console :

Rectangle@(10,10)(w=40.0,h=30.0)
Rectangle@(-10,-10)(w=50.0,h=30.0)
Rectangle@(-10,-10)(w=60.0,h=50.0)

Vous pouvez utiliser la classe java.awt.Point pour représenter une coordonnée dans le plan.

Solution

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
 
25 
26 
public class Rectangle
{
    private Point lowerleft;
    private double width, height;
 
    public Rectangle (Point lowerleft, double width, double height)
    {
        this.lowerleft = (Point) lowerleft.clone();
        this.width = width;
        this.height = height;
    }
 
    public Rectangle fusion (Rectangle r)
    {
        int x = Math.min (lowerleft.x, r.lowerleft.x);
        int y = Math.min (lowerleft.y, r.lowerleft.y);
        double w = Math.max (lowerleft.x + width, r.lowerleft.x + r.width) - x;
        double h = Math.max (lowerleft.y + height, r.lowerleft.y + r.height) - y;
        return new Rectangle (new Point (x, y), w, h);
    }
 
    public String toString()
    {
        return "Rectangle@(" + lowerleft.x + "," + lowerleft.y + ")(w=" + width + ",h=" + height + ")";
    }
}

Les variables d'instance et le constructeur sont très faciles à écrire. Il ne faut juste remarquer que les objets de type Point sont mutables et penser à faire une copie avec la méthode clone. La méthode toString est également triviale.

Il reste enfin la méthode fusion qui doit renvoyer un nouveau rectangle, il faut donc calculer la position de son coin inférieur gauche et ses dimensions. Pas besoin d'ajouter des méthodes accesseurs puisqu'on a accès à toutes les variables d'instance des objets Rectangle puisque la méthode est définir dans cette classe.

Question 4

Écrivez une classe Watch qui représente une horloge. Cette horloge est caractérisée par des heures et des minutes. Vous devez proposer deux manières différentes pour créer un nouvel objet : soit on ne spécifie aucun paramètre et l'horloge est initialement réglée à 00h00, soit on spécifie l'heure initiale que l'on souhaite. De plus, la classe Watch doit posséder une méthode printHour qui affiche l'heure courante sous la forme XXhXX (par exemple 16h37). Il faut également deux méthode tick. La première, sans paramètre, permet de faire avancer l'heure de une minute, tandis que la seconde, qui prend un entier n en paramètre, permet de faire avancer l'heure de n minutes.

Voici un exemple qui utilise un objet Watch.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
public static void main (String[] args)
{
    Watch w = new Watch (23, 58);
    w.printHour();
 
    w.tick();
    w.printHour();
 
    w.tick (5);
    w.printHour();
}

L'exécution de ce programme affiche sur la sortie standard :

23h58
23h59
00h04

Solution

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
 
41 
42 
public class Watch
{
    private int hours, minutes;
 
    public Watch()
    {
        this (0, 0);
    }
 
    public Watch (int h, int m)
    {
        hours = h;
        minutes = m;
    }
 
    public void tick()
    {
        minutes++;
        if (minutes == 60)
        {
            hours++;
            minutes = 0;
            if (hours == 24)
            {
                hours = 0;
            }
        }
    }
 
    public void tick (int n)
    {
        for (int i = 0; i < n; i++)
        {
            tick();
        }
    }
 
    public void printHour()
    {
        System.out.println ((hours < 10 ? "0" : "") + hours + "h" + (minutes < 10 ? "0" : "")+ minutes);
    }
}

La classe doit posséder deux variables d'instance entière pour représenter les heures et les minutes. Il faut ensuite proposer deux manières pour construire un objet Watch, on va donc définir deux constructeurs : le premier sans paramètre et le second qui prend deux paramètres. Le premier constructeur appelle simplement le second avec this.

Ensuite, la méthode printHour doit afficher l'heure. On a tout fait en une seule instruction en utilisant l'opérateur conditionnel mais vous pouvez bien entendu le faire avec des if.

Enfin, pour finir, il faut deux version de la méthode tick. On commence par écrire celle qui fait avancer l'heure d'une minute. On incrémente la variable d'instance minutes. Si les minutes arrivent à 60, on les remet à zéro et on incrémente hours. Si les heures atteignent 24, on les remet à zéro.

La méthode tick qui prend n en paramètre est maintenant facile à faire, il suffit d'appeler n fois la méthode tick sans paramètres que l'on vient de définir.

Question 5

Écrivez une classe Book qui représente un livre. Pour faire simple, un livre possède un titre (String), un numéro ISBN unique (String) et enfin une série d'auteurs représentés par un tableau de Person (voir question 2).

Définissez un constructeur en faisant bien attention que les tableaux sont muables en Java. Ensuite, définissez une méthode qui permet de tester si une personne fait partie des auteurs du livre. Voici sa signature :

public boolean isAnAuthor (Person p);

Afin de pouvoir écrire cette méthode facilement, on va modifier la classe Person : ajoutez un attributs int idnb qui représente le numéro d'identité de la personne (qui est donc unique pour chaque personne). Modifiez le constructeur en conséquence et définissez également la méthode equals.

Solution

Voici tout d'abord les changements apportés à la classe Person.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
public class Person
{
    // ...
    private int idnb;
 
    public Person (String name, GregorianCalendar birthdate, int idnb)
{
// ...
        this.idnb = idnb;
}
 
    public boolean equals (Object o)
    {
        if (o instanceof Person)
        {
            Person p = (Person) o;
            return idnb == p.idnb;
        }
        return false;
    }
}

Voici maintenant la classe Book. Pour le constructeur, afin de prendre en compte la muabilité des tableaux, on a utilisé la méthode arraycopy de la classe System pour faire une copie du tableau (vous pouvez bien sûr faire la copie vous-mêmes avec une boucle).

Enfin, il reste la méthode isAnAuthor à écrire, ce qu'on fait simplement avec une boucle for.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
import java.util.Arrays;
import java.util.GregorianCalendar;
 
public class Book
{
    private String title;
    private String isbn;
    private Person[] authors;
 
    public Book (String title, String isnb, Person[] authors)
    {
        this.title = title;
        this.isbn = isbn;
        this.authors = new Person[authors.length];
        System.arraycopy (authors, 0, this.authors, 0, authors.length);
    }
 
    public boolean isAnAuthor (Person p)
    {
        for (int i = 0; i < authors.length; i++)
        {
            if (authors[i].equals (p))
            {
                return true;
            }
        }
        return false;
    }
}

Question 6

Modifiez la classe Rectangle que vous avez écrite à la question 3 de telle sorte que celle-ci implémente l'interface Shape suivante :

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
public interface Shape
{
    /**
     * @pre -
     * @post La valeur renvoyée contient le périmètre de cette forme
     */
    public double getPerimeter();
 
    /**
     * @pre -
     * @post La valeur renvoyée contient la surface de cette forme
     */
    public double getArea();
}

Écrivez ensuite une classe Circle qui représente un cercle. Un cercle est identifié par un centre (x, y) et un rayon r. Cette classe doit également implémenter l'interface Shape. Voici un exemple de création d'un cercle centré en (1, 1) et de rayon 2.5 :

Shape c = new Circle (new Point (1, 1), 2.5);
System.out.println (c.getArea());

Ce code affiche 19.634954084936208 à la console.

Solution

La première partie de l'exercice n'est pas bien difficile, il faut simplement définir toutes les méthodes de l'interface dans la classe. On ajoute tout d'abord la clause implements, ensuite on définit les deux méthode getPerimeter et getArea.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
public class Rectangle implements Shape
{
    // ...
 
    public double getPerimeter()
    {
        return 2 * (width + height);
    }
 
    public double getArea()
    {
        return width * height;
    }
}

La seconde partie n'est pas très compliquée non plus, le plus dur est peut-être de se rappeler que le périmètre d'un cercle est donné par 2πr et sa surface par πr2.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
public class Circle implements Shape
{
    private Point center;
    private double radius;
 
    public Circle (Point c, double r)
    {
        center = c;
        radius = r;
    }
 
    public double getPerimeter()
    {
        return 2 * Math.PI * r;
    }
 
    public double getArea()
    {
        return Math.PI * r * r;
    }
}

Question 7

Écrivez une classe Coin qui représente une pièce à deux faces que l'on peut lancer. La classe doit posséder, outre un constructeur sans paramètre, trois méthodes dont voici les signatures :

public void toss()
public boolean isHead()
public boolean isTail()

La première méthode permet de lancer la pièce. La seconde permet de tester si la face visible de la pièce est pile et la troisième méthode teste si la face visible est face. Pour rappel, la méthode Math.random() renvoie un double entre 0 (compris) et 1 (non-compris).

Écrivez ensuite un programme TestCoin qui crée une pièce, la lance 100 fois d'affilé et affiche le nombre total de pile et de face qu'il y a eu en tout sur les 100 lancés.

Solution

On va utiliser une variable d'instance booléenne qui retient si la face visible est pile. On aurait pu utiliser un autre type de donnée, mais comme l'état d'une pièce n'a que deux valeurs possibles, le type booléen est le plus naturel.

Le constructeur appele la méthode toss pour initialiser l'état de l'objet. La méthode toss choisit un nombre au hasard entre 0 et 1 et met à jour l'état de l'objet. Et les méthodes isHead et isTail sont triviales.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
public class Coin
{
    private boolean head;
 
    public Coin()
    {
        toss();
    }
 
    public void toss()
    {
        int n = (int) (Math.random() * 2);
        head = (n == 0);
    }
 
    public boolean isHead()
    {
        return head;
    }
 
    public boolean isTail()
    {
        return ! isHead();
    }
}

On créé tout d'abord l'objet Coin et une variable pour compter le nombre de pile. Ensuite, on fait 100 lancers avec une boucle for et enfin, on affiche le nombre de pile et de face obtenus en tout.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
public class TestCoin
{
    public static void main (String[] args)
    {
        Coin c = new Coin();
        int nbheads = 0;
        for (int i = 0; i < 100; i++)
        {
            c.toss();
            if (c.isHead())
            {
                nbheads++;
            }
        }
        System.out.println (nbheads + " piles et " + (100 - nbheads) + " faces");
    }
}

Vous pouvez télécharger la liste des questions. Si vous avez des problèmes ou que vous ne comprenez pas bien une question, rendez-vous sur le forum consacré aux exercices.

  • Espace membre
  • Learning Center
  • Les forums
  • Livre d'or
  • Imprimer
  • Boutique
  • Info
  • Règlement
  • Erreur
  • Newsletter

MyPagerank.Net

Firefox 3.6

Browse Happy logo

Open Clip Art Library

Join our Facebook Group

Twitter

Copyright © 2000-2018 UKO. Toute reproduction strictement interdite sans autorisation du webmaster

Valid XHTML 1.1 !
Valid CSS2 !
Level Triple-A conformance icon, W3C-WAI Web Content Accessibility Guidelines 1.0
ICRA Internet Content Rating Association
Creative Commons License
Site optimisé pour Firefox avec une résolution 1024x768 --- Page chargée en 0.0846939 secondes --- This site uses Thumbshots previews