Download Inner Classes

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
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
Related documents