// Programming can be understood in terms of a transformation from one set of data to another. // Throughout the course of the transformation, the actual computation, the original set of // data does *not* change. // +------+ // | | // Input >| BB |< Output // | | // +------+ // Input \ne Output. // In fact, Input and output might not be related at all. /* Problem statement: Carl's Rental Cars needs a program to figure out important info about its rental fleet. For example, Carl is particularly interested in these pieces of information: Engine (1) Mileage (2) Cylinders (3) Hybrid Engine? (4) Diesel Engine? Car (1) Engine (2) Four Wheel Drive? (3) Manual Transmission? (4) Snow Tires? From the information, Carl would like to have a program that: (1) Add mileage to a car's mileage (1.5) Make a new car object with the mileage increased (2) Determine if car is low maintenance, i.e. a MT car which is not clean (3) Determine if car is winter ready, i.e. four wheel drive with snow tires (4) Determine if engine is fuel efficient. */ class Engine { // For the first part of this class and indeed in many cases, // we should treat created objects as set in stone, including the // fields. This simplifies program design and reasoning immensely. int mileage; int cylinders; boolean isHybrid; boolean isDiesel; // We have no choice here. This is just a fill-in-the-blank pattern // we must follow: // Name-of-class(comma delimited types and names) { // this.name-of-field = name // ... // } Engine(int mileage, int cylinders, boolean isHybrid, boolean isDiesel) { this.mileage = mileage; this.cylinders = cylinders; this.isHybrid = isHybrid; this.isDiesel = isDiesel; } // new Engine(1000, 6, true, true).addMileage(100) == 1100 // new Engine(6000, 8, false, false).addMileage(400) == 6400 // To add this Engine's mileage to some additional mileage int addMileage(int additionalMileage) { // ... anotherEngine.EngineMethod() ... this.mileage ... this.cylinders ... // ... this.isHybrid ... this.isDiesel ... additionalMileage return this.mileage + additionalMileage; } // new Engine(1000, 6, true, true).isClean() == false // new Engine(1000, 6, true, false).isClean() == true // new Engine(1000, 6, false, true).isClean() == false // new Engine(1000, 6, false, false).isClean() == false // To determine if this Engine is clean burning boolean isClean() { // ... anotherEngine.EngineMethod() ... this.mileage .. this.cylinders ... // ... this.isHybrid ... this.isDiesel return this.isHybrid && !this.isDiesel; } // new Engine(1000, 6, true, false).isFuelEfficient() == true // new Engine(1000, 4, true, false).isFuelEfficient() == true // new Engine(1000, 4, true, false). isFuelEfficient() == true // new Engine(1000, 6, false, false).isFuelEfficient() == false // To determine if this Engine is fuel efficient boolean isFuelEfficient() { // ...anotherEngine.EngineMethod() ... this.mileage ... this.cylinders ... // ...this.isHybrid ... this.isDiesel return (this.isHybrid || (this.cylinders < 6)); } // new Engine(1000, 6, true, false).getNewEngineWithMoreMiles(1000) -> // new Engine(2000, 6, true,false) // Get a new Engine representation with this Engine's attributes plus additional Mileage Engine getNewEngineWithMoreMiles(int additionalMileage) { // ... anotherEngine.EngineMethod() ... this.mileage ... this.cylinders .... // ... this.isHybrid ... this.isDiesel ... additionalMileage return new Engine(this.mileage + additionalMileage, this.cylinders, this.isHybrid, this.isDiesel); } } class Car { Engine myEngine; boolean isFourWheelDrive; boolean isManualTransmission; boolean hasSnowTires; Car(Engine myEngine, boolean isFourWheelDrive, boolean isManualTransmission, boolean hasSnowTires) { this.myEngine = myEngine; this.isFourWheelDrive = isFourWheelDrive; this.isManualTransmission = isManualTransmission; this.hasSnowTires = hasSnowTires; } // new Car(new Engine(1000, 6, true, true), true, true, true).addMileage(1000) == 2000 // new Car(new Engine(2500, 4, false, false), false, false, false).addMileage(200) == 2700 // Add another car's engine mileage with this car's engine mileage int addMileage(int additionalMileage) { // ... myEngine.EngineMethod() ... this.isFourWheelDrive ... this.isManualTransmission // ... this.hasSnowTires ... additionalMileage return this.myEngine.addMileage(additionalMileage); } // Let's consider the procedure of how to construct new objects // new Car(new Engine(1000, 4, true, true), true, false, false).getCarWithIncreasedMileage(400) // -> new Car(new Engine(1400, 4, true, true), true, false, false) // new Car(new Engine(2500, 4, false, true), false, true, false).getCarWithIncreasedMileage(200) // -> new Car (new Engine(2700, 4, false, true), false, true, false) // Get a new Car representation identical to this Car with increased mileage by given amount Car getCarWithIncreasedMileage(int additionalMileage) { // ... myEngine.EngineMethod() .. this.isFourWheelDrive ... this.isManualTransmission // ... this.hasSnowTires ... additionalMileage return new Car(this.myEngine.getNewEngineWithMoreMiles(additionalMileage), this.isFourWheelDrive, this.isManualTransmission, this.hasSnowTires); } // new Car(new Engine(100, 4, true, true), true, false, false).isWinterReady() == false // new Car(new Engine(100, 4, true, true), true, false, true).isWinterReady() == true // new Car(new Engine(100, 4, true, true), false, true, false).isWinterReady() == false // new Car(new Engine(100, 4, true, true), false, true, true).isWinterReady() == false // Determine if this car is winter-ready, i.e., has snow tires and four wheel drive boolean isWinterReady() { // ... myEngine.EngineMethod() ... this.isFourWheelDrive ... this.isManualTransmission ... // ... this.hasSnowTires return this.hasSnowTires && this.isFourWheelDrive; } // new Car(new Engine(100, 4, true, false), true, true, true).isLowMaintenance() == false // new Car(new Engine(100, 4, false, false), true, true, true).isLowMaintenance() == true boolean isLowMaintenance() { // ... myEngine.EngineMethod() ... this.isFourWheelDrive ... this.isManualTransmission ... // ... this.hasSnowTires return this.isManualTransmission && (!this.myEngine.isClean()); } }