* Un objet, c'est: - De l'état (données) - Du comportement (fonctionnalité) Le tout bien encapsulé (enrobé) à travers la définition de la classe. Éviter l'exhibitionnisme. * Exemples ** Complexe: Protocole (idée de haut niveau) 1. Point du plan (2d) 2. Addition: translation (somme vectorielle) 3. Multiplication: rotation (4. Inversions additive et multiplicative) ** Complexe (cartésien) a + b*i public class Complex { double a, b; public Complex (double a, double b) { this.a = a; this.b = b; } public Complex add (Complex b) { return new Complex(this.a + b.a, this.b + b.b); } public Complex mul (Complex b) { return new Complex(this.a * b.a - this.b * b.b, this.a * b.b + this.b * b.a); } } c1 = a + b*i c2 = c + d*i c3 = c1 + c2 = ??? c4 = c1 * c2 = ??? (ac + bci + adi - bd) ** Complexe (polaire) r, theta Invariant? c1 = (r, t) = r * exp(i * t) c2 = (s, u) c3 = c1 * c2 = ??? c4 = c1 + c2 = ??? public class Complex { double angle, rayon; public Complex(double r, double a) { this.angle = a; this.rayon = r; } } ** Complexe (adaptif) Plus simple de passer en polaire pour des multiplications, en cartésien pour des additions. Invariant: ? (r, theta) OU (a, b) public class Complex { double d1, d2; boolean cartesian; public Complex ...; [...] void switch_to_polar() { if (!cartesian) return; double r = Math.sqrt(d1 * d1 + d2 * d2); double theta = Math.atan2(d1, d2); d1 = r; d2 = theta; cartesian = false; } [...] void switch_to_cartesian() { if (cartesian) return; double a = d1 * Math.cos(d2); double b = d1 * Math.sin(d2); d1 = a; d2 = b; cartesian = true; } public Complex add (Complex b) { this.switch_to_cartesian(); b.switch_to_cartesian(); return new Complex(this.d1 + b.d1, this.d2 + b.d2, true); } public Complex mul (Complex b) { this.switch_to_polar(); b.switch_to_polar(); return new Complex(this.d1 * b.d1, this.d2 + b.d2, false); } } ** Complexe (paresseux) Un complexe ne change pas. On peut garder les deux valeurs en tout temps! Invariant: ? public class Complex { double angle, rayon, a, b; boolean got_polar, got_cartesian; public double getAngle() { this.compute_polar(); return angle; } getFoo... public Complex(double x, double y, boolean in_polar) { ... got_polar = in_polar; got_cartesian = !in_polar; } [...] void compute_polar() { if (got_polar) return; double r = Math.sqrt(a * a + b * b); double theta = Math.atan2(a, b); rayon = r; angle = theta; got_polar = true; } public void setAngle (double angle) { this.angle = ...; got_cartesian = false; } [...] void compute_cartesian() { double a = rayon * Math.cos(angle); double b = rayon * Math.sin(angle); this.a = a; this.b = b; } public Complex add (Complex b) { return new Complex(this.getA() + b.getA(), this.getB() + b.getB(), false); } public Complex mul (Complex b) { this.compute_polar(); b.compute_polar(); return new Complex(this.rayon * b.rayon, this.angle + b.angle, true); } } * Retour