Éléments de programmation objet

Méthodes

Principe

Programmation objet :

Au lieu d’accéder aux champs directement, on utilise des méthodes

Méthode

Exemple:

class Vecteur {
  double x,y;
  Vecteur(double x, double y) {
    this.x = x;
    this.y = y;
  }
  double module() {
    return Math.sqrt(this.x*this.x+this.y*this.y);
  }
  double argument() {
    return Math.atan2(this.y,this.x);
  }
}

Types de méthodes

Exemple:

class Voiture {
  String couleur;
  String marque;
  String modele;
  Voiture(String couleur, String marque, String modele) {
    this.couleur=couleur;
    this.marque=marque;
    this.modele=modele;
  }
  boolean estBlanche() {
    return this.couleur.equals("blanc");
  }
  void repeint(String couleur) {
    this.couleur = couleur;
  }
}

Appel de méthode

Pour appeler une méthode, la syntaxe est objet.méthode(paramètres)

Ce sont les champs de l’objet réféencé par objet qui sont utilisés et/ou modifiés par la méthode

En cas d’appel de méthode sur la référence null, la machine virtuelle lève une exception NullPointerException (l’équivalent en plus propre de Segmentation Fault).

Exemple:

class Prog {
  public static void main(String[] args) {
    Voiture voiture = new Voiture("blanc","Renault","4L");
    if (voiture.estBlanche())
      System.out.println("La voiture est blanche");
    else
      System.out.println("La voiture n'est pas blanche");
    voiture.repeint("blanc");
    if (voiture.estBlanche())
      System.out.println("La voiture est blanche");
    else
      System.out.println("La voiture n'est pas blanche");
  }
}

Méthode toString

Quand on affiche un objet ou que l’on le concatène avec l’opérateur +, l’objet est converti en chaîne en appelant la méthode toString(). Elle doit être public (pour indiquer que la machine virtuelle a le droit de l’utiliser, comme le main).

class Voiture {
  String couleur;
  String marque;
  String modele;
  Voiture(String couleur, String marque, String modele) {
    this.couleur=couleur;
    this.marque=marque;
    this.modele=modele;
  }
  boolean estBlanche() {
    return this.couleur.equals("blanc");
  }
  void repeint(String couleur) {
    this.couleur = couleur;
  }
  public String toString() {
    return this.marque+" "+this.modele+" de couleur "+this.couleur;
  }
}

class Prog {
  static String excesDeVitesse(Voiture v, int vitesse) {
    return v+" à "+vitesse+" km/h";
  }
  public static void main(String[] args) {
    Voiture voiture = new Voiture("noire","Peugeot","RCZ");
    System.out.println(voiture);
    System.out.println(excesDeVitesse(voiture,254));
  }
}

Partie publique, partie privée

Pour séparée les fonctionalités de l’implémentation, nous disposons de deux modificateurs:

Il y a également deux niveaux intermédiaires. L’un sera vu en même temps que la notion de paquetage et l’autre en même temps que la notion d’héritage.

Dorénavant, tout élément d’une classe devra être soit privé soit public.

Comme les classes seront toutes publiques, elles devront être chacune dans un fichier de même nom terminé par .java.

Privé : partie implémentation

On déclare privé ce qui sert à l’implémentation des fonctionalités

Exemple :

public class GeometrieDuCercle {
  private double rayon;
  public GeometrieDuCercle(double rayon) {
    this.rayon=rayon;
  }
  private double r2() {
    return rayon*rayon;
  }
  private double r3() {
    return rayon*rayon*rayon;
  }
  public double diametre() {
    return 2*rayon;
  }
  public double circonference() {
    return Math.PI*diametre();
  }
  public double aire() {
    return Math.PI*r2();
  }
  public double aireSphere() {
    return 4*Math.PI*r2();
  }
  public double volume() {
    return 4*Math.PI/2*r3();
  }
} 

Public : utilisable par les tiers

Tout ce qui est public est utilisable par d’autre.

Contrat moral : si on utilise que la partie publique d’un objet (Java l’oblige), toute version future de la classe sera compatible avec ce qui est écrit.

Exemple :

Rien de privé entre instances de la même classe

Privé ne veut pas dire réservé à soi mais réservé à sa classe.

Exemple :

class Vecteur {
  private double x;
  private double y;
  public Vecteur(double x,double y) {
    this.x=x;
    this.y=y;
  }
  public void ajoute(Vecteur v) {
    this.x+=v.x:
    this.y+=v.y;
  }
}

Quand il n’y a pas ambigüité avec les paramètres ou variables locales des méthodes ou constructeurs, on peut ommettre this. (déconseillé au début car cela fait des erreurs curieuses).

class Personne {
  private String prenom;
  private String nom;
  public Personne(String prenom, String nom) {
    this.prenom=prenom;
    this.nom=nom;
  }
  public void mariage(Personne personne) {
    nom=nom+"-"+personne.nom;
  }
}

Fonctions

Il est possible d’avoir des fonctions avec le mot-clef static.

Ce mot-clef signifie: « appelable sans référence à l’objet ».

Exemple de message d’erreur quand on accède à un champ depuis une fonction:

Error: non-static variable x cannot be referenced from a static context

On apelle donc souvent une fonction méthode statique mais le terme fonction est plus approprié.

Variables globales

Il est aussi possible d’avoir des variables globales: elle sont communes à tout le programme. Il suffit de mettre le mot-clef static devant le champ :

On appelle donc souvent une variable globale champ statique mais le terme variable globale est plus approprié. En cas d’ambigüité pas de this. réservé aux éléments non statiques mais à partir du nom de la classe.

Exemple :

class ObjetPayant() {
  private static int compteur;
  private double valeur;
  public ObjetPayant(double valeur) {
    compteur++;
    this.valeur = valeur;
  }
  public static void paye(double compteur) {
    ObjetPayant.compteur-=compteur;
  }
}

Bonnes pratiques

Les champs sont toujours privés

On ne rend publique que ce qui vraiment utilisé par d’autres objets

Une classe a une seule responsabilité

On essaye dans la mesure du possible de mettre les variables globales dans des classes sans champ (exception : les constantes, voir prochain cours)