/** * C'est une classe pour illustrer le * comportement des objets dans le cours IFT1015. * * Il s'agit d'un objet pour représenter des points 2D. * Les attributs d'un point sont ses coordonnées x et y. * * @author csuros */ public class Point { // // --------------------------------------------------------------- // -------------- Variables de la classe (variables statiques) // --------------------------------------------------------------- // /** * Variable de la classe utilisée pour définir une valeur de référence. * Cette variable est déclarée public, donc on * donne le droit à tous les autres classes de * changer sa valeur --- même à une valeur négative. */ public static double TRES_LARGE_DISTANCE = 10.0; /** * Variable de la classe à laquelle l'accès est réservée * pour cette classe même. */ private static int nombreDePointsInstancies = 0; /** * Accès contrôlé au nombre d'instanciations. * * @return combien de fois un constructeur était appelé */ public static int nombreDInstanciations() { return nombreDePointsInstancies; } // // --------------------------------------------------------------- // -------------- Variables de l'objet (variables non-statiques // --------------------------------------------------------------- // /** * Variable d'objet x pour stocker la coordonnée X d'un point. * Chaque instance de Point a son propre variable x, visible * dans cette classe Point dans les méthodes statiques et * non-statiques. * */ private double x; /** * Variable d'objet x pour stocker la coordonnée Y d'un point. * Chaque instance de Point a son propre variable x, visible * dans cette classe Point dans les méthodes statiques et * non-statiques. */ private double y; /** * Méthode de l'objet: accès contrôlé à la coordonnée X. * * @return la coordonnée X associée avec cette instance de Point */ public double lireX() { return x; } // // --------------------------------------------------------------- // -------------- Constructeur // --------------------------------------------------------------- // /** * On redéfinit le constructeur par défaut. * Un constructeur publique, sans arguments, * existe par défaut si on ne * déclare aucun autre constructeurs. * Ce constructeur par défaut est équivalent au code * * public Point(){} * * Ici, on veut aussi compter les instances différentes qu'on a * créee. */ public Point() { // Les variables de l'objet existent // déjà ici, donc on a accès // à x et y, // ainsi qu'à toutes les // méthodes de l'objet. // Quand même, on n'en sert pas ici // parce qu'on est content // avec les valeurs initiales // de 0.0 pour x et y et il n'y // rien à faire pour l'objet même. // On a accès à des variables statiques // dans un contexte non-statique. // La variable nombreDePointsInstancies // est d'accès privé, mais c'est OK // parce qu'on est dans la même classe. nombreDePointsInstancies++; } // // --------------------------------------------------------------- // -------------- Méthodes de la classe (méthodes statiques) // --------------------------------------------------------------- // /** * Une méthode publique qui calcule la distance entre deux points. * * @param P1 Premier point * @param P2 Deuxième point * @return La distance euclidienne entre les deux points. */ public static double distance(Point P1, Point P2) { double dx = P1.x-P2.x; double dy = P1.y-P2.y; // Math.sqrt est une méthode statique // dans la classe Math qui // calcule la racine d'une expression double. return Math.sqrt(dx*dx+dy*dy); } /** * Une méthode publique qui calcule la distance * entre cette instance et un autre point. * * @param P2 L'autre point * @return Distahnce euclidienne entre moi et l'autre point */ public double distanceDe(Point P2) { double dx = x-P2.x; // la première variable x est celle de l'instance définie par le contexte de l'appel double dy = y-P2.y; // une altérnative return Math.sqrt(dx*dx+dy*dy); // Une autre altérnative beaucoup peu plus cryptique // return (new Point(dx,dy)).norme(); // voire constructeur Point(x,y) plus bas } /** * Une méthode publique pour calculer * la norme euclidienne racine(x*x+y*y). * * L'implantation utilise une valeur précalculée. */ public double norme() { return r; } /** * Variable privée pour précalculer * la distance de l'origine (0,0), * c'est-à-dire la norme de ce point. */ private double r; // initialisée à 0.0, ce qui est correct parce que x=y=0.0 à l'instanciation /** * Accès contrôlé pour changement de coordonnées. * Ici, on peut faire toute l'administration * nécessaire (comme recalcul de r). * * @param nX nouvelle valeur de la coordonnée X * @param nY nouvelle valeur de la coordonnée Y */ public void changerCoordonnees(double nX, double nY) { x = nX; y = nY; // Il faut recalculer la norme (variable r). recalculeNorme(); } /** * Comme on calcule la norme euclidienne tout le temps, il * vaut la peine de se servir d'une méthode privée * qui fait le calcul. * Notez qu'on peut utiliser le même nom * qu'une atre méthode: il n'y a pas d'ambiguïté parce que * les arguments sont différents. * (Part contre, on ne pourrait pas * avoir une méthode * public static double norme().) * * @param dx Longueur de la vecteur en X * @param dy Longueur de la vecteur en Y * @return Norme euclidienne */ private static double norme(double dx, double dy) { return Math.sqrt(dx*dx+dy*dy); } /** * Une méthode de l'objet avec accès privé. * Cette méthode doit être appelée * chaque fois que les coordonnées changent. */ private void recalculeNorme() { // On peut utiliser la méthode statique privée qu'on vient de définir r = norme(x,y); } /** * Une méthode pour dire si on est trop loin de l'origine. * C'est un test simple de comparer la norme avec la * variable de la classe TRES_LARGE_DISTANCE. * Cette dernière peut être changer * par une autre classe pour avoir des résultats différents * dans cette méthode. * @return si la norme est tres grande */ public boolean tropLoin() { return norme()>TRES_LARGE_DISTANCE; } // // --------------------------------------------------------------- // -------------- This // --------------------------------------------------------------- // /** * Méthode de l'objet: accès contrôlé à la coordonnée Y. * * @return la coordonnée Y associée avec cette instance de Point */ public double lireY() { // Ici, le mot-clé this fournit le contexte // de l'instance à laquelle la requête est adressée // Il n'y a pas de confusion possible, donc // on pourrait simplement écrire // return y; return this.y; } /** * Méthode de l'objet: changement contrôlé de la coordonnée X. */ public void changeX(double x) { // Ici le mot-clé this est tout à fait nécessaire. // En écvrivant x=x (sans "this."), // toutes les deux variables // sont l'argument x de cette fonction // et l'attribut x de l'instance ne cghange pas this.x = x; // Ne pas oublier que la norme peut changer avec une nouvelle coordonnée x. recalculeNorme(); } /** * Méthode statique publique pour décaler un point. * * @param P Point qu'on veut décaler * @param dx décalage X * @param dy décalage Y */ public static void decaler(Point P, double dx, double dy) { // Un exemple pour montrer qu'on peut changer // l'état d'un objet passé comme argument // parce qu'ils sont passés comme référence P.x+=dx; P.y+=dy; P.recalculeNorme(); // et voilà P est à une nouvelle position } // // --------------------------------------------------------------- // -------------- Constructeurs // --------------------------------------------------------------- // /** * Constructeur avec initialisation de coordonnées * * @param x Coordonnée x * @param y Coordonnée y */ public Point(double x, double y) { // On appelle le constructeur // sans argument pour assurer // que chaque instance est comptée this(); // Il n'y a pas de confusion pour // les variables x y ici et les variables x y // de l'objet: les arguments x y cachent // les variables de l'objet. // Pour commettre une erreur, il faut la faire // explicitement: changerCoordonnees(this.x,this.y); changerCoordonnees(x,y); } /** * Constructeur pour créer une copie * * @param P instance qu'on veut copier */ public Point(Point P) { // Tout simplement ... this(P.x,P.y); } /** * Instanciation d'un point à distance 1 de * la l'origine. * C'est un constructeur privé * parce qu'on ne veut l'utiliser * que dans cette classe (dans main ci-bas). * * @param phi angle de la vecteur mènant au point. */ private Point(double phi) { this(Math.cos(phi),Math.sin(phi)); } /** * Méthode pour construire une déscription * de cet objet. * * @return String décrivant les attributs. */ public String description() { return "Point("+x+","+y+") norme "+r; } /** * Code de test. * * @param args Argument de la ligne de commande */ public static void main(String[] args) { Point A = new Point(0.2,0.4); Point B = new Point(0.3,0.6); System.out.println("J'ai "+nombreDInstanciations()+" points"); System.out.println("Variable A est une référence à l'adresse "+A+" ce qui est "+A.description()); System.out.println("Variable B est une référence à l'adresse "+B+" ce qui est "+B.description()); decaler(B,-0.3,0.4); System.out.println("Je viens de décaler B: "+B.description()); Point C = new Point(Math.PI/5.0); System.out.println("Variable C est une référence à l'adresse "+C+" ce qui est "+C.description()); Point D = B; System.out.println("Jusqu'ici il y a "+nombreDInstanciations()+" points"); System.out.println("Variable D est une référence à l'adresse "+D+" ce qui est "+D.description()); decaler(D, 99.0, 98.0); System.out.println("Je viens de décaler D: "+D.description()); System.out.println("Mais B aussi: "+B.description()); B = new Point(); B = new Point(0.20081030); // Notez l'erreur numérique dans le calcul de la norme de B - cela devrait être 1.0 System.out.println("Variable B est une référence à l'adresse "+B+" ce qui est "+B.description()); System.out.println("Jusqu'ici il y a "+nombreDInstanciations()+" points"); decaler(D, -99.0, -98.0); System.out.println("Je viens de décaler D de douveau: "+D.description()); System.out.println("Mais B reste où il était: "+B.description()); } }