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);
}
}
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.
public class AlarmProcessor {An alternative implementation using inheritance might look like this:
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;
}
}
}
public class ResidentialAlarmProcessor {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 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...
}
}
public class AlarmProcessorFactory {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.
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;
}
}
}
public class Speaker {You can override the "sayHello" method in a sublass, e.g.
public void sayHello() {
System.out.println("hello");
}
}
public class FrenchSpeaker extends Speaker {Now FrenchSpeaker's "sayHello" will automatically override the base class version, e.g.
public void sayHello() {
System.out.println("bonjour");
}
}
public class SpeakerExample {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 static void main(String[] args) {
Speaker englishSpeaker = new Speaker();
Speaker frenchSpeaker = new FrenchSpeaker();
englishSpeaker.sayHello(); //prints "hello"
frenchSpeaker.sayHello(); // prints "bonjour"
}
}
public class FrenchSpeaker extends Speaker {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.
public void sayHello() {
super.sayHello();
System.out.println("bonjour");
}
}