Skip to main content
Object Oriented Software Design
Object Oriented Software Design

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 abstract classes 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:

Switch s1Switch s2Safety switchORNOTANDValve

1. The component hierarchy

Difficulty: Rx

We’ll build up the following hierarchy over this lab and the next few:

  • Component — the abstract root of the hierarchy. It provides getId(), identifying the component (for now, this can just delegate to Object’s own toString(), which gives you a unique-enough label like And@1a2b3c for 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 by And, Or, and any future two-input gate, without committing to what each one actually computes.

As a class diagram (abstract classes in italics):

ComponentSwitchValveGateNotTwoInputGateAndOr

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, with in1/in2 fields and setIn1/setIn2 methods), then And and Or extending it.
  • Write a CircuitTest class with an empty main, 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 // build section, create an array of Component and instantiate the example circuit’s components into it: three switches (s1, s2, a safety switch), an Or, a Not, an And, and a Valve — matching the example circuit above. Wiring comes next, so leave // wire empty for now.
  • Write a method printIds(Component[] components) that prints each component’s getId(), and call it from // display on your array.

2. Describing components

Difficulty: Rx

Add 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 to printIds, and call it from // display.