Abstract classes
Sometimes it is useful to put off defining the methods of a class. In this case we
do it in order to create a complex number without deciding ahead of time what its
internal representation should be.
complex/Complex.java |
1 | package complex; |
2 | |
3 | public abstract class Complex { |
4 | abstract public double re(); |
5 | abstract public double im(); |
6 | abstract public double ang(); |
7 | abstract public double rad(); |
8 | |
9 | public Complex add(Complex c) { |
10 | return new Cart(re()+c.re(),im()+c.im()); |
11 | } |
12 | public Complex mul(Complex c) { |
13 | return new Polar(rad()*c.rad(),ang()+c.ang()); |
14 | } |
15 | public Complex sqrt() { |
16 | return new Polar(Math.sqrt(rad()),0.5*ang()); |
17 | } |
18 | public String toString() { |
19 | return "("+re()+"+"+im()+"i)"; |
20 | } |
21 | } |
Note the use of keyword "abstract" both on the class name and on the public methods
that have not been specified.
In the code above we perform our addition, multiplication, or find a sqrt() with either the polar or Cartesian methods, depending
on which is easier for us to write. Better yet, we only have to write each of these methods once, and re-use
them by inheritance.
complex/Cart.java |
1 | package complex; |
2 | |
3 | public class Cart extends Complex { |
4 | private double re, im; |
5 | public Cart(double re,double im) { |
6 | this.re = re; |
7 | this.im = im; |
8 | } |
9 | public double re() { return re; } |
10 | public double im() { return im; } |
11 | public double rad() { return Math.sqrt(re*re+im*im); } |
12 | public double ang() { return Math.atan2(im,re); } |
13 | } |
For each representation of a complex number, we only need to fill in the four methods for obtaining the "coordinates."
complex/Polar.java |
1 | package complex; |
2 | |
3 | public class Polar extends Complex { |
4 | private double rad, ang; |
5 | public Polar(double rad,double ang) { |
6 | this.rad = rad; |
7 | this.ang = ang; |
8 | } |
9 | public double re() { return rad*Math.cos(ang); } |
10 | public double im() { return rad*Math.sin(ang); } |
11 | public double rad() { return rad; } |
12 | public double ang() { return ang; } |
13 | } |
$ javac complex/Polar.java
|
Now that we've got all our classes defined, we can do a compile. Java is smart enough that it will know it needs
class Complex and Cart, and it will automatically find the source files and compile them for us.
TryComplex.java |
1 | import complex.*; |
2 | |
3 | public class TryComplex { |
4 | public static void main(String[] args) { |
5 | Complex a = new Cart(3,4); |
6 | Complex b = new Cart(5,12); |
7 | Complex c = a.add(b); // c = a + b |
8 | Complex d = c.mul(b); // d = (a + b)*b |
9 | System.out.println("a="+a); |
10 | System.out.println("b="+b); |
11 | System.out.println("c="+c); |
12 | System.out.println("d="+d); |
13 | System.out.println("sqrt(a)="+a.sqrt()); |
14 | } |
15 | } |
$ javac TryComplex.java
| $ java TryComplex
a=(3.0+4.0i)
b=(5.0+12.0i)
c=(8.0+16.0i)
d=(-152.0+176.0i)
sqrt(a)=(2.0+1.0i)
|
Now we try out our new classes, printing out various values. Nifty!
|