Object Oriented Programming

What is a class?

A class is basically a type defintion for objects. For example, in a racing game application, you can write a single Car class. In the game, there will be many different car objects, all of them of type Car. In Java, almost every type is a class. The only exceptions to this rule are the primitive types (e.g. char, byte, int, long, float, double, bool). A class combines both state and behaviour into one entity: This is a powerful organizing principle for software development, and leads to a somewhat different style of programming as compared to non-object-oriented languages.

Example Car class:

public class Car {

private static final int MAX_SPEED = 50;

public static final int BLUE = 0;
public static final int RED = 1;

private int positionX;
private int positionY;
private float directionAngle;
private int speed = 10;

private int number;
private int color;

public Car(int number, int color) {
this.number = number;
this.color = color;
}

public int getNumber() {
return number;
}

public int getColor() {
return color;
}

public void increaseSpeed() {
speed+=10;
if (speed > 10)
speed = 10;
}

public void decreaseSpeed() {
speed-=10;
if (speed < 0)
speed = 0;
}

public void turnLeft() {
directionAngle += 45;
directionAngle %= 360;
}

public void turnRight() {
directionAngle -= 45;
directionAngle %= 360;
}

public void move() {
int x = positionX + speed*Math.cos(directionAngle);
int y = positionY + speed*Math.sin(directionAngle);
if checkBounds(x, y) {
positionX = x;
positionY = y;
}
}

public String toString() {
return "color " + color + "; "
+ "number = " + number + "; "
+ "x = " + positionX + "; "
+ "y = " + positionY + "; "
+ "speed = " + speed + "; "
+ "directionAngle = " + directionAngle;
}

private void checkBounds(int x, int y) {
//check boundaries
}
}

Here is a trivial example using this class:

public class TestDrive {
public static void main(String[] args) {
Car blue = new Car(1, Car.BLUE);
Car red = new Car(2, Car.RED);

blue.move();
red.move();
System.out.println(blue);
System.out.println(red);

blue.move();
red.move();
System.out.println(blue);
System.out.println(red);

blue.move();
red.move();
System.out.println(blue);
System.out.println(red);

blue.turnRight();
blue.turnRight();
System.out.println(blue);
System.out.println(red);

red.turnLeft();
red.turnLeft();
System.out.println(blue);
System.out.println(red);

blue.move();
red.move();
System.out.println(blue);
System.out.println(red);

blue.move();
red.move();
System.out.println(blue);
System.out.println(red);

blue.move();
red.move();
System.out.println(blue);
System.out.println(red);
}
}

References, Objects, Methods

    Car blueCar = new Car(1, Car.BLUE);

In this example code fragment, "blueCar" is a reference to an object of type "Car". "new Car(1, Car.BLUE)" invokes the constructor for the car class. This constructor returns an object of type Car. The "blueCar" reference now points to this object. Note: Many references can point to the same object. Java has built-in garbage collection so once no more references are pointing to an object, the memory for the object is automatically collected.

Inheritance and Polymorphism (aka Overriding Methods)

The idea of inheritance is to to extend the functionality of a class without modifying that class directly. As a rule, your subclass should have more specific behaviour than its superclass. Java uses a "single model of inheritance." This means that a subclass can extend only one superclass. Any  additional contracts must be satisfied using interfaces. In other words, a class can inherit from only one superclass, but can implement any number of interfaces (more on this later). There are a couple of scenarios where using inheritance makes sense: In the first case, you simply don't have the source code for the class you are using, perhaps because it was provided to you as part of a third-party framework. In Java, the simplest way to "add" functionality to that class is to extend it. In the second case, you do have the source code, but you still don't want to directly modify the source code for the class. The reason for extending a class using inheritance is to keep the code in the original class relatively simple and readable. After all, modifying code increases the chances of unexpected bugs. Also, you can simplify the code by avoiding "conditional statement" problem, e.g.
public class AlarmProcessor {
public void processAlarm(int alarmType) {
switch (alarmType) {
case (AlarmTypes.RESIDENTIAL)
//do something here...
break;
case (AlarmTypes.COMMERCIAL)
//do something else here...
break;
case (AlarmTypes.INDUSTRIAL)
//diffrent from the others....
break;
}
}
}
An alternative implementation using inheritance might look like this:
public class ResidentialAlarmProcessor {
public void processAlarm() {
//do something here....
}
}


public class CommercialAlarmProcessor {
public void processAlarm() {
//do something else here....
}
}


public class IndustrialAlarmProcessor {
public void processAlarm() {
//different from the others...
}
}
This type of approach is especially useful when AlarmProcessor has a large number of methods and all of them vary based on the alarm type. Adding a new alarm type or changing behaviour for an alarm type can be quite difficult and risky with the conditional-riddled code described earlier. The OO approach is to put the creation of the object in one place -- you still need conditionals to decide which object to create -- but from there on you just use a reference to an interface or base class and polymorphism does the rest of the work for you.

public class AlarmProcessorFactory {
public static AlarmProcessor createAlarmProcessor(int alarmType) {
switch (alarmType) {
case (AlarmTypes.RESIDENTIAL):
return new ResidentialAlarmProcessor();
break;
case (AlarmTypes.COMMERCIAL):
return new CommercialAlarmProcessor();
break;
case (AlarmTypes.INDUSTRIAL):
return new IndustrialAlarmProcessor();
break;
default:
throw new UnknownAlarmTypeException();
break;
}

}
}
Note: Object orientation and polymorphism are genuinely useful approaches to software development, but they can also be overused. Resist the temptation to use inheritance and polymorphism all over the place in your programming. If these techniques make your programs more difficult to work with, then you're not using them properly. If you're interested in more information about object-oriented patterns, check out books like Design Patterns by the GoF, Refactoring by Fowler, and Refactoring to Patterns, by Kerievsky.

How Polymorphism Works

Polymorphism is the ability to override the behaviour of a method. The idea is that you have a method in a base class, e.g.
public class Speaker {
public void sayHello() {
System.out.println("hello");
}
}
You can override the "sayHello" method in a sublass, e.g.
public class FrenchSpeaker extends Speaker {
public void sayHello() {
System.out.println("bonjour");
}
}
Now FrenchSpeaker's "sayHello" will automatically override the base class version, e.g.
public class SpeakerExample {
public static void main(String[] args) {
Speaker englishSpeaker = new Speaker();
Speaker frenchSpeaker = new FrenchSpeaker();

englishSpeaker.sayHello(); //prints "hello"
frenchSpeaker.sayHello(); // prints "bonjour"
}
}
You can access the base class's version of a method with the "super" keyword. By the way, a call to the super class method can be made at the beginning or at the end of a function.
public class FrenchSpeaker extends Speaker {
public void sayHello() {
super.sayHello();
System.out.println("bonjour");
}
}
Note: Chaining polymorphic functions in an inheritance tree can be a source of problems. Since an overriding function replaces the super class's behaviour, every overriding function in the chain has to make a call to super.

Interfaces and Abstract Classes

Interfaces and abstract classes are very similar in that they both are used to sepcify a "contract." The idea of such "contract" or "interface" oriented programming is to make a clean distinction between using a class and the gory details of implementation. An abstract class is a class which forces the  details of implementation for some of its methods (the abstract methods, of course) on a sublass. For example, see discussion of the "template method" design pattern at http://home.earthlink.net/~huston2/dp/templateMethod.html. An interface is a pure abtract class. In other words an interface looks like an abstract class which has only abstract methods. However, one key difference between an interface and a pure abstract class in Java is that a class can implement as many interfaces as it likes while it can only extend one class. Using interfaces and abstract classes wisely will allow you to develop code that is organized in terms of loosely coupled modules which communicate among one another via interfaces. The details of how functionality is implemented within each module is thus concealed from other modules. See for example the facade design pattern at http://www.csc.calpoly.edu/~dbutler/tutorials/winter96/patterns/tutorial.html.

Access Control

Java classes, methods, and attributes can specify their level of visibility to other classes. There are four levels of visibility, in order of increasing visibility: private; package-level, protected, and public. Here is what they mean:
Note: Classes can be public, which means any other class can see them, or they can have package-level access, which means any other classes in the same package can see them.   Unlike methods and attributes, classes cannot themselves be private or protected.

Below are code examples to illustrate the basic ideas:

package x
public class A {
    private int ivar1;
    int ivar2; //package-level access
    protected ivar3;

    public int getIvar1() {
        return ivar1; //this is ok -- same class
    }
}


package x
public class B {
    private A a = new A();

    public int getIvar2() {
        return a.ivar2; //ok -- A and B are in the same package              
    }
}

package y
public class C {
    private A a = new A();

    public int getIvar2() {
        return a.ivar2; //error -- A and C are not in the same package              
    }

    public int getIvar1() {
        return a.getIvar1(); //ok -- A's getIvar1() method is public; anyone can call it
    }
}

package y
public class D extends A {
    public int getIvar2() {
        return a.ivar2; //error -- A and D are not in the same package              
    }

    public int getIvar3() {
       return ivar3; //ok -- this is a protected attribute of the superclass

}