The class Fraction: Putting all we have seen together Bruce Eckel, Thinking in Java, 4th edition, PrenticeHall, New Jersey, cf. http://mindview.net/Books/TIJ4 [email protected] José Valente de Oliveira 4-1 The class Fraction Problem: Develop a class Fraction representing rational numbers. Representation: n – numerator d – denominator d>0 mdc (|n| , d ) = 1 Class invariant (condição invariante de instância) (máximo divisor comum – gcd in English) Ex. 2/4 == 1/2 Operations n1/d1 + n2/d2 = (n1d2 + n2d1) / (d1 * d2); n1/d1 – n2/d2 = (n1d2 - n2d1) / (d1 * d2); n1/d1 * n2/d2 = n1 * n2 / (d1 * d2); (n1/d1) / (n2/d2) = n1* d2 / (n2* d1); with n2 ≠ 0 (n1/d1) == (n2/d2) <=> n1 == n2 and d1 == d2 n1/d1 < n2/d2 <=> n1d2 < n2d1 1 A possible client class Main { public static void main(String [] args) { Fraction f = new Fraction(4, 6); Fraction g = new Fraction(1, -2); Fraction s = new Fraction(); s = f.add(g); boolean b = f.less(g); System.out.println(s); WeSystem.out.println(b); would like to use operators } such as +, < but Java does not } support operator overloading (yet) Class invariants Where to enforce class invariants? right when the object is created: in the constructor Additionally any method that modifies instance variables directly should not be defined public int setNumerator (int n) { num = n; } If such methods must be implement (avoid them if possible) they must also enforce class invariants, when modifying instance variables. 2 /** @version 1.0 */ public class Fraction { private int num, den; public Fraction() { this(0); } public Fraction(int n) { num= n; den = 1; } public Fraction (int n, int d) { if (d == 0) { System.err.print("Fraction.denominator() cannot be zero"); System.exit(1); // We will have to improve this later } if (d < 0) { this.num = -n; this.den = -d; } else { num = n; // same as this.num =n; den = d; } int k =mdc(Math.abs(num), den); mdc (|n| , d ) = 1 num /= k; den /= k; eg.: 8/16 == 1/2, } /** @version 1.0 */ public class Fraction { private int num, den; public Fraction() { this(0); } public Fraction(int n) { num= n; den = 1; } public Fraction (int n, int d) { if (d ==0) { System.err.print("Fraction.denominator() cannot be zero"); System.exit(1); // We will have to improve this later } Referencing the receiver if (d<0) { this.num = -n; this.den = -d; } else { num = n; // same as this.num =n; den = d; } int k =mdc(Math.abs(num), den); num /= k; den /= k; } d>0 k=8 with this 3 /** Calcula o máximo divisor comum dos seus parâmetros @param m inteiro positivo @param n inteiro positivo @pre-condition: m >0 e n >0 @return inteiro com o máximo divisor comum entre m e n */ private int mdc( int m , int n ){ int r; while (( r = m % n ) != 0 ) { m = n; n = r; } return n; } } // end of class /** retorna uma nova instância da classe com o resultado da multiplicação do recetor this pelo argumento that @param that uma Fraction @return n1/d1 * n2/d2 = n1n2 / (d1 * d2); @version 1.0 */ By creating a new public Fraction mult(Fraction that) { object, the class int n = this.num * that.num; invariant is enforced // ou int n = num * that.num; int d = this.den * that.den; return new Fraction(n, d); } class Main { public static void main(String [] args) { //.. Fraction s = f.mult(g); } } [email protected] José Valente de Oliveira 3-8 4 Where are we so far? Java A little bit of History Goals and characteristics First programs First classes Control of visibility Sintaxe Assignment semantics Initialization of objects: constructors References Method overloading Acessing the receiver: the reference this [email protected] José Valente de Oliveira 3-9 Check point: what’s the output? class Point { private int x,y; public void setX(int nx) public int getX() //… } { x = nx; } { return x; } public class Check{ public static void main(String[] args) { Point origin = new Point(); Point B = origin; B.setX(1); System.out.println(origin.getX()); } } [email protected] José Valente de Oliveira 3-10 5 Scope Each program element has a scope — the context where it can be referred to using its simple name. { Elements can have the same name when their scope does not overlap. int k = 0; // ... } for (int k = 0; k< 3; k++) { // OK! No problem! } Scope Each program element has a scope — the context where it can be referred to using its simple name. { If the scopes of two int k = 0; variables overlap, the // ... variable defined in the inner scope takes for (int k = 0; k< 3; k++) { precedence over the // loop k hides outer k variable with the same } name in the outer scope. } 6 Scope The Scope of an element is determined by the place where the element is defined. Variables with the same name but different scope are different variables. Possible scopes in Java: Local Function File Class Prototype Package class Point { private int x, y; public Point(int x, int y) { // x, y: the same name // in a different scope } // … } Scope The Scope of an element is determined by the place where the element is defined. Variables with the same name but different scope are different variables. Possible scopes in Java: Local Function File Class Prototype Package class Point { private int x, y; public Point(int x, int y) { this.x = x; this.y = y; } // … } 7 Questions to address next Given a problem, how to find the objects that will provide the solution? What are the rules in an object society? How are they organized? How they communicate between which other? [email protected] José Valente de Oliveira 4-15 8