Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Inner Classes Classes can be declared inside classes, functions, and block commands. We call such classes inner classes. When defined inside another class, we call the enclosing class an outer class. For example, Computer is an outer class, while Processor and MemoryModule are inner classes: class Computer { class Processor { public void fetchExecute() { ... } private void execute(int instruction) { ... } private int sp, pc, reg1, reg2, reg3; // registers // etc. } class MemoryModule { public int read(int address) { ... } public void write(int value, int address) { ... } // etc. } private MemoryModule m1, m2; private Processor cpu; // etc. } Inner classes are like inner classes in C++, except an instance of a (non static) Java inner class is always encapsulated by an instance of the outer class. For example, to declare an instance of Processor: Computer c = new Computer(...); // create encapsulating instance of outer class Computer.Processor p = c. new Processor(...); Compare this with C++: Computer::Processor *p = new Computer::Processor(...); // no Computer instance needed! This means members of the outer class are accessible to the inner class. For example, we can refer to m1, one of the memory modules defined in Computer, inside Computer.Processor.fetchExecute(): class Computer { class Processor { public void fetchExecute() { do { Instruction instr = m1.read(pc++); execute(instr); } while(instr != HALT); } // etc. } // Processor // etc. } How does this work? Inner class methods like Computer.Processor.fetchExecute() get two implicit parameters, this and Computer.this. For example, assume objects representing networks are defined: class Network { public boolean isConnected(Computer c) { ... } // etc. } Computer.Processor.execute() can check for connectivity by passing Computer.this: class Computer { private Network myLAN; class Processor { public void execute(int instruction) { if (instruction == REG) // register network ID if (myLAN.isConnected(Computer.this)) { ... } else ... else if ... } // etc. } // Processor // etc. } 2 What are inner classes good for? They can be used as grouping mechanisms: class Utils { static class IOTools { ... } static class ThreadTools { ... } static class MathTools { ... } // etc. } But we already have packages. Two other applications are abstract factories and assemblies. When we study the event delegation model, we will see a third application: Inner Listeners. Assemblies An assembly is an object with fixed components. Assume the following declarations are made: interface Engine { public int getPower(); // in bhp public int getCylinders(); // 4, 6, 8? public int getSize(); // in cc public void show(); } interface Transmission { public boolean isManual(); public int getSpeeds(); public void show(); } 3 abstract class Car { public Car(String s) { style = s; } // getters public String getStyle() { return style; } public Engine getEngine() { return engine; } public Transmission getTransmission() { return trans; } public void show() { System.out.println("Style = " + style); engine.show(); trans.show(); } // attributes protected String style; // sedan, coup, sport, utility, etc. protected Engine engine; protected Transmission trans; } We can neatly hide implementations of Engine and Transmission inside extensions of Car. For example: Buicks class Buick extends Car { public Buick(String s, int cc, boolean man) { super(s); engine = (Engine) new EngineImpl(cc); trans = (Transmission) new TransmissionImpl(man); } public void show() { System.out.println("\n*** Buick ***"); super.show(); } 4 class EngineImpl implements Engine { public EngineImpl(int cc) { size = cc; } public int getPower() { return size + 10; } public int getSize() { return size; } public int getCylinders() { if (size < 200) return 6; else return 4; } public void show() { System.out.println("Engine specs:"); System.out.println("\t" + getCylinders() + " cylinders"); System.out.println("\tsize = " + size + "cc"); System.out.println("\tpower = " + getPower() + "bhp"); } private int size; } // EngineImpl class TransmissionImpl implements Transmission { public TransmissionImpl(boolean m) { man = m; } public boolean isManual() { return man; } public int getSpeeds() { if (man) return 4; else return 3; } public void show() { System.out.print("Transmission: "); if (man) System.out.println("Manual 4 speed"); else System.out.println("Automatic 3 speed"); } private boolean man; } // TransmissionImpl } // Buick 5 Fords class Ford extends Car { public Ford(String s, int cc) { super(s); engine = (Engine) new EngineImpl(cc); trans = (Transmission) new TransmissionImpl(); } public void show() { System.out.println("\n### Ford ###"); super.show(); } class EngineImpl implements Engine { public EngineImpl(int cyls) { cylinders = cyls; } public int getSize() { if (cylinders == 4) return 140; else if (cylinders == 6) return 200; else if (cylinders == 8) return 240; else return 0; } public int getPower() { return getSize()/2 + 85; } public int getCylinders() { return cylinders; } public void show() { System.out.println("Engine specs:"); System.out.println("\t" + cylinders + " cylinders"); System.out.println("\tsize = " + getSize() + "cc"); System.out.println("\tpower = " + getPower() + "bhp"); } private int cylinders; } // EngineImpl 6 // stopped making manuals class TransmissionImpl implements Transmission { public TransmissionImpl() { } public boolean isManual() { return false; } public int getSpeeds() { return 3; } public void show() { System.out.println("Automatic 3 speed"); } } // TransmissionImpl } // Ford Assemblies User's don't have to create Buick and Ford engines to go with their Buick and Ford cars. There is no danger of putting a Ford engine inside a Buick: class Assembly { public static void main(String[] args) { Car c1 = new Buick("Sedan", 180, true); Car c2 = new Buick("Coup", 250, false); Car c3 = new Ford("Sedan", 6); Car c4 = new Ford("Sedan", 8); c1.show(); c2.show(); c3.show(); c4.show(); } } 7 Program Output *** Buick *** Style = Sedan Engine specs: 6 cylinders size = 180cc power = 190bhp Transmission: Manual 4 speed *** Buick *** Style = Coup Engine specs: 4 cylinders size = 250cc power = 260bhp Transmission: Automatic 3 speed ### Ford ### Style = Sedan Engine specs: 6 cylinders size = 200cc power = 185bhp Automatic 3 speed ### Ford ### Style = Sedan Engine specs: 8 cylinders size = 240cc power = 205bhp Automatic 3 speed Abstract Factories A factory method is an ordinary Java method that creates and returns a new object: Product factoryMethod() { return new Product1(...); } An abstract factory or Kit is an interface or abstract class that specifies a collection of related factory methods. For example, assume Window, Dialog, and Menu are interfaces: interface Window { ... } interface Menu { ... } interface Dialog { ... } A GUI factory is a collection (interface or abstract class) of factory methods: interface GUIFactory { public Window makeWindow(...); public Menu makeMenu(...); public Dialog makeDialog(...); // etc. } 8 GUI factory implementations are platform specific: class Win32GUIFactory implenments GUIFactory { ... } class SolarisGUIFactory implements GUIFactory { ... } class MacGUIFactory implements GUIFactory { ... } Assume the Engine and Transmission interfaces are as before, and assume Car is a concrete class instead of an abstract class. A car factory must provide factory methods for each car component: interface CarFactory { // factory methods public Engine makeEngine(int x); public Transmission makeTransmission(boolean x); } Here are two implementations of CarFactory: Ford Factory class FordFactory implements CarFactory { public Engine makeEngine(int n) { return new EngineImpl(n); } public Transmission makeTransmission(boolean x) { return new TransmissionImpl(x); } class EngineImpl implements Engine { ... } // as in Ford.EngineImpl class TransmissionImpl implements Transmission { ... } // as in Ford.TransmissionImpl } 9 Buick Factory class BuickFactory implements CarFactory { public Engine makeEngine(int n) { return new EngineImpl(n); } public Transmission makeTransmission(boolean x) { return new TransmissionImpl(x); } class EngineImpl implements Engine { ... } // as in Buick.EngineImpl class TransmissionImpl implements Transmission { ... } // as in Buick.TransmissionImpl } Assembly The same car factory can point to a Ford factory or a Buick factory: public class Assembly { public static void main(String[] args) { CarFactory f; Car c1 = new Car("Sedan"); Car c2 = new Car("Coup"); f = new FordFactory(); c1.setEngine(f.makeEngine(8)); c1.setTransmission(f.makeTransmission(false)); f = new BuickFactory(); c2.setTransmission(f.makeTransmission(true)); c2.setEngine(f.makeEngine(210)); c1.show(); c2.show(); } } Program Output Style = Sedan Engine specs: 8 cylinders size = 240cc power = 205bhp Automatic 3 speed Style = Coup Engine specs: 4 cylinders size = 210cc power = 220bhp Transmission: Manual 4 speed 10