Lab #2: A Class Hierarchy for Logic Components
This lab starts a running project that continues through the rest of the course: a small simulator for circuits built out of logic gates (AND, OR, NOT) wired to switches on their inputs and output devices on their outputs. Each lab adds a layer on top of what the previous one built, so keep your code from this point on — you’ll need it again.
Objectives
- Design an abstract class hierarchy that mirrors a real domain (logic components).
- Practice
abstractclasses as factoring points, and simple inheritance chains. - Write a first polymorphic method (
description()) shared across an entire hierarchy.
The domain
A circuit is built from components wired together: switches feed values in, gates combine them, and output devices (here, a single kind — a valve) receive the result. For example, a circuit might have two switches feeding an OR gate, a third “safety” switch feeding a NOT gate, and both of those feeding an AND gate whose output drives a valve:
1. The component hierarchy
Difficulty: RxWe’ll build up the following hierarchy over this lab and the next few:
Component— the abstract root of the hierarchy. It providesgetId(), identifying the component (for now, this can just delegate toObject’s owntoString(), which gives you a unique-enough label likeAnd@1a2b3cfor free).Switch— a component with no input of its own; it represents a user-controlled input to the circuit.Valve— a component with a single input (in), representing an output device.Gate— the abstract root of all logic gates.Not— a gate with a single input (in).TwoInputGate— abstract; factors out the two-input wiring (in1,in2) shared byAnd,Or, and any future two-input gate, without committing to what each one actually computes.
As a class diagram (abstract classes in italics):
Here is the starting skeleton — copy it into a components directory and build on it (also available pre-packaged as components.tar if you’d rather download it than retype it):
public abstract class Component {
public String getId() {
return super.toString(); // "ClassName@hash", inherited from Object
}
}
public class Switch extends Component {
}
public class Valve extends Component {
protected Component in;
public void setIn(Component c) {
in = c;
}
}
public abstract class Gate extends Component {
}
public class Not extends Gate {
protected Component in;
public void setIn(Component c) {
in = c;
}
}
Your task:
- Add
TwoInputGate(abstract, within1/in2fields andsetIn1/setIn2methods), thenAndandOrextending it. - Write a
CircuitTestclass with an emptymain, structured with three clearly-marked sections you’ll fill in over this lab and the next:// build,// wire,// display.
Test it
In CircuitTest:
- In the
// buildsection, create an array ofComponentand instantiate the example circuit’s components into it: three switches (s1,s2, a safety switch), anOr, aNot, anAnd, and aValve— matching the example circuit above. Wiring comes next, so leave// wireempty for now. - Write a method
printIds(Component[] components)that prints each component’sgetId(), and call it from// displayon your array.
2. Describing components
Difficulty: RxAdd a polymorphic public String description() method that ends up available on every component class — the cleanest way to do that is one concrete implementation in Component itself (the shared root), which each subclass overrides only if its own description needs to look different (a Switch, having no input at all, needs a different shape than a gate). The string should be built from:
- the component’s own id (
getId()), - for components that have input(s), the id of whatever is connected there, or the literal string
"not connected"if nothing is.
For example, an unconnected-on-input-1, connected-on-input-2 And gate might describe itself as:
And@48d6c16c in1: not connected in2: Not@5abb7465
A single-input component describes itself the same way, just with one in: instead of two:
Not@2c1f9a4 in: Switch@7d3b810
A Switch has no input to report at all — its description() can just be its id on its own, e.g. Switch@7d3b810.
Test it
Back in CircuitTest:
- In
// wire, connect a few of your components to each other (try more than one configuration as you test). - Write a method
printDescriptions(Component[] components)analogous toprintIds, and call it from// display.