Computer Science 15-110, Spring 2010
Class Notes: Getting Started with Writing Classes
In class this week we started to write our own classes.
The first class we are writing is a simple Fraction class. We would like the following code to work:
// We want this, but can't have it (darn!) public static void main(String[] args) { Fraction f1 = 2/3; Fraction f2 = 3/9; Fraction f3 = f1*f2; System.out.println(f1); System.out.println(f2); System.out.println(f3); }
Unfortunately, we cannot overload the / and * operators highlighted above to work this way (you can in some other languages, but not in Java).
So instead we'll settle on this version, which is similar but written in a way that we actually can support:
// Compare this to the version above public static void main(String[] args) { Fraction f1 = new Fraction(2,3); Fraction f2 = new Fraction(3,9); Fraction f3 = f1.times(f2); System.out.println(f1); System.out.println(f2); System.out.println(f3); }
And here is the code we wrote in class (warts and all) to do it:
class FractionDemo {
public static void main(String[] args) {
Fraction f1 = new Fraction(2,3);
Fraction f2 = new Fraction(3,9);
Fraction f3 = f1.times(f2);
System.out.println(f1.toString()); // 2/3
System.out.println(f2); // 1/3
System.out.println(f3); // 2/9
System.out.println(f3+".getNum()=" + f3.getNum());
System.out.println(f3+".getDen()=" + f3.getDen());
System.out.println("Now you can 'safely' set the num");
System.out.println("and it will still be reduced:");
f3.setNum(9);
System.out.println(f3);
System.out.println("But the fact that Fraction is now");
System.out.println("mutable leads to this ugliness...");
Fraction f4 = new Fraction(2,3);
Fraction f5 = f4;
f5.setNum(5);
System.out.println(f4);
System.out.println(f5);
System.out.println("Conclusion: it was a bad idea to");
System.out.println("make Fractions mutable");
}
}
class Fraction { // instance variables (the data for each instance) private int num, den; // Constructor // First store the paramters in the instance variables // Then reduce the fraction. public Fraction(int num, int den) { this.num = num; this.den = den; reduce(); } // reduce helper method // Called by the constructor and also by the mutators ("setters"). private void reduce() { if (this.den == 0) return; int gcd = gcd(this.num, this.den); this.num /= gcd; this.den /= gcd; } // gcd helper method // This is static because it does not refer to any instance variables. public static int gcd(int x, int y) { // gcd(x,y) == gcd(y,x%y) while (y != 0) { int r = x%y; x = y; y = r; } return x; } // accessors ("getters") public int getNum() { return this.num; } public int getDen() { return this.den; } // mutators ("setters") // bad idea for Fraction class, but included here // for demonstrational purposes. public void setNum(int num) { this.num = num; reduce(); } // toString instance method // Convert the instance variables into a String. public String toString() { if (den == 1) return "" + this.num; return this.num + "/" + this.den; } // times instance method // Multiply "this" Fraction by "that" Fraction and return the result // as a new Fraction. public Fraction times(Fraction that) { int numerator = this.num * that.num; int denominator = this.den * that.den; Fraction result = new Fraction(numerator, denominator); return result; } }
carpe diem - carpe diem - carpe diem - carpe diem - carpe diem - carpe diem - carpe diem - carpe diem - carpe diem