3.6 Inheritance
This section under major construction.
Inheritance.
Language support to define relationships among objects. Two main types of inheritance: interfaces and subtyping. Main advantage of subtyping = code reuse. Main advantage of interfaces = dynamic dispatch.Interfaces.
Interfaces provide a mechanism for specifying a relationship between otherwise unrelated classes, typically by specifying a set of common methods that each implementing class must contain. Client can only interact with object through listed methods. Interface inheritance is widely used to implement callbacks or dynamic dispatch. Functions are not first class objects in Java.Real-valued functions.
Goal: an integration library that takes a real-valued function as input. Create an interface for a real-valued function.To define an interface in Java, you use the keyword interface instead of class, and specify the API (without the implementation code). Here's an interface for a real-valued function of one variable.
Here's a sample class that implements the Function interface. By including implements Function in the class definition, you are promising to implement a method named eval() that takes a double argument and returns a double. Not doing so leads to a compile-time error.
public interface Function { double eval(double x); }
Here's a sample method that integrates any Function using the trapezoid rule. It produces accurate results assuming the function is sufficiently smooth. (Alternative: write a method to plot any function over a given interval.)
public class NormalPDF implements Function { private double mu; private double sigma; public NormalPDF(double mu, double sigma) { this.mu = mu; this.sigma = sigma; } public double eval(double x) { double num = Math.exp( -(x - mu) * (x - mu) / (2 * sigma * sigma)); double den = sigma * Math.sqrt(2 * Math.PI)); return num / den; } public double inverse(double x) { ... } }
public class TrapezoidRule { public static double integrate(Function f, double a, double b, int N) { double h = (b - a) / N; // step size double sum = 0.5 * (f.eval(a) + f.eval(b)); // area for (int i = 1; i < N; i++) { double x = a + h * i; sum = sum + f.eval(x); } return sum * h; } }
Newton's method.
Or define interface DifferentiableFunction.java for twice-differentiable function.Sqrt.java implements the function f(x) = c - x^2.
public interface DifferentiableFunction { double eval(double x); double diff(double x); }
Use Newton's method to find a real root of a sufficiently smooth function, given that you start sufficiently close to a root. When method converges, it does so quadratically. Should Newton.java contain a static method findRoot(f, x0) or be an object?
public class Newton { private DifferentiableFunction f; public Newton(DifferentiableFunction f) { this.f = f; } public double findRoot(double x0) { double eps = 1e-10; double x = x0; double delta = f.eval(x) / f.diff(x); while (Math.abs(delta) > (eps / x)) { x = x - delta; delta = f.eval(x) / f.diff(x); } return x; } }
Natural ordering.
The Comparable interface for finding the maximum of a bunch of elements (or sorting them).Slight difficulty - what to do about generics? The interface is Comparable<Key>.
Program Counter.java is a version of Program Counter.java from Section 3.4 that makes it implement the Comparable interface.
Note: Java arrays are covariant so String[] can be used when a method's signature contains Comparable[].
// max of two Comparables public static Comparable max(Comparable a, Comparable b) { if (a.compareTo(b) <= 0) return a; return b; } // max of an array of Comparables public static Comparable max(Comparable[] a) { if (a == null || a.length == 0) return null; Comparable max = a[0]; for (int i = 0; i < a.length; i++) if (a[i].compareTo(max) > 0) max = a[i]; return max; }
When defining a class, you need to specify that it implements a given interface. To make Date implement the Comparable<Date> interface, do the following. (A bit awkward for first example since it uses generics.)
Make Counter comparable.
public class Date implements Comparable<Date> { ... public int compareTo(Date b) { ... } }
Event-based programming.
Event-based programming is a powerful example that extols the virtues of callbacks. Provides more refined control over interactive methods in StdDraw. We now describe how the support for various user interactions (mouse clicks and keystrokes) within Draw.java by using the interface DrawListener.java.Note that you must implement all of the interface functions (perhaps with empty bodies) even if you don't need them.
public interface DrawListener { public void mousePressed (double x, double y); public void mouseDragged (double x, double y); public void mouseReleased(double x, double y); public void keyTyped(char c); }
- Keyboard input. Program MovingJoker.java displays an image (the joker) and moves it when the user types one of the keys 'i', 'j', 'k', or 'l'.
- Mouse input.
Program Squares.java
takes a command line parameter N and draws an N-by-N
grid of cells.
When the user clicks in a cell, draw a blue circle.
Repeat, but alternate colors between red and blue.
Mouse clicks and dragging.
Or use a hex grid and create Lite-Brite images.
- Mouse dragging.
Program Graffiti.java
waits for the user to click and drag the mouse, and draws a
trail as the user drags the mouse. It changes colors as the user
drags.
Limitations of Java interfaces. Java interfaces suffer two important limitations: you cannot specify constructors or static methods in the interface.
Danger: if you subsequently change the interface, this can break all of the classes that implement it.
Subtyping.
"Code reuse is extremely important but difficult to achieve." -Joshua Bloch. Subtyping is a way to describe family of types when one subclass (child) "inherits" instance variables and instance methods from a superclass (parent). Define a new type that inherits properties from existing type. Base class specifies similarities; derived class specifies differences. It is a powerful technique that enables the programmer to change the behavior of a class and add functionality without rewriting the entire class from scratch. For example, we might have a superclass called Mammal, and subclasses Dog and Cat. We might also have further subclasses of Dog, say GermanShepherd and LabradorRetriever. (Not a compelling example since it's not organized by data similarities (e.g., have hair, have mammary glands, are warm-blooded) instead of similar behavior (e.g., provide companionship, give milk, pull a vehicle).Note: subclass contains more methods than superclass. Subtyping is widely used for building extensible libraries, including GUI. In Java, you can only inherit from one superclass. Single inheritance vs. multiple inheritance.
Method polymorphism.
Polymorphism = many forms, e.g., water can be a liquid, solid (ice), or gas (steam). dynamic binding Method to be called is determined at run-time, and depends on the type of the object.We override a method to provide specialized behavior. Overriding a method means to redefine a method in a subclass that was defined in a superclass. When you do this, the object in the subclass has two methods with the same name and signature.
Give simple example.
- Swing GUI hierarchy. Button -> AbstractButton -> JComponent -> Container -> Component -> Object.
- Java exceptions. Exception -> RuntimeException -> NullPointerException
- Supersymmetry particle classification. Physicists have classified particles into the following taxonomy. For example, an electron is a type of lepton (feels weak force but not strong force), which is a type of fermion (particles that make up matter).
- Liskov Substitution Principle. If A inherits from B, then whenever you expect to use a B object, you can safely use an object of type A instead and you will get the desired behavior. That is, objects in the subclass must behave in a manner consistent with promises made in the API of the superclass. Instead of is-a-kind-of relationship, it's better to think is-a-substitute-for. When you use extends Java checks that the two classes have compatible method signatures, but does not check that the behavior is consistent.
- Open-closed principle. Software should be designed to be open for extension (can extend the module to behave in new ways), but closed for modification (no one should ever change the source code). Ex: square, circle, triangle. Don't want a switch statement in base class for each type.
Object.
In Java, all classes inherit from the universal superclass named Object.- equals(). Implementing equals(). Nearly impossible to do correctly a type and a subtype.
- toString(). The toString() method is implemented in Object, and hence common to all classes. This method returns a String representation of the object. The default behavior on many systems is to return the memory address where the object is stored. The principle of inheritance is what enables System.out.println() and StdOut.println() to "know" how to print an object when you supply a method called toString(). When you call System.out.print() with an object as an argument, the system automatically invokes the object's toString method. Which toString() method does the system use? It uses the one in the subclass, if it is defined, otherwise it uses the one from the superclass.
Turtle graphics.
Extend Turtle in various ways. Make DeluxeTurtle that adds color, etc. Add a version that supports error checking. For example, throw a TurtleOutOfBounds exception if turtle goes outside designated boundary.Problems with subtyping.
Improper use of subtyping can create lots of programming nightmares since it often violates encapsulation and makes future changes more troublesome. Subtyping is sometimes derided as the "goto statement of the 1990s." Coupling = reliance of one part of a program on another. Prime tenet of OOP is to reduce the level of coupling.- Circle-ellipse problem.
The key to understanding when to use inheritance is the
circle-ellipse
problem.
Circle extends Ellipse is OK if both are immutable types, but not if
Ellipse can be squashed asymmetrically (e.g., has a method to change its
width and height).
A properly designed subclass must have only less strict preconditions
and postconditions. When Circle inherits from Ellipse,
there are additional preconditions (the width and height are equal).
From a geometric viewpoint, a circle is a kind of ellipse, but it does not
have the same behavior in this example (because you can mutate the
width and height parameters).
The is-a-kind-of rule is necessary, but not sufficient.
Intuition with when to use
inheritance is often wrong.
Another wrong approach might be to make Ellipse extend Circle. Bad idea: since Circle may have a method radius() that makes no sense for an asymmetric Ellipse. This problem is compounded if Circle has an implementation for circumference() that is 2 * Math.PI * radius().
- Fragile base class problem.
With subtyping,
the subclass becomes tightly coupled with the superclass implementation.
This is sometimes referred to as the fragile base class problem.
The design is fragile because if you want to change the superclass, you
must know the details of all of the subclasses or risk breaking them.
This is not always possible, e.g., if you are Sun Microsystems and are
re-implementing
a Java library which has been subclassed by millions of programmers!
Moreover, by overriding methods, the subclass can break the contracts
promised by the superclass.
This is especially difficult if the programmers developing the
subclass and superclass are different.
For these reasons, many experienced programmers recommend avoiding
subtyping whenever possible.
When subtyping, be sure that the subclasses
depend only on the behavior of the superclass, not on the implementation.
Reference.
Simple example: adding a method to the superclass with different return type than an existing method in a subclass (won't compile). Violates the "is a" rule: Sun's implementation of Stack which inherits from Vector and Sun's implementation of Properties which inherits from HashTable. Subtle example: use inheritance to create a subclass of Stack that counts the total number of elements inserted by maintaining an extra field, overriding add and addAll. Problem: superclass implements addAll by invoking add so we get twice the count when using addAll. We could then rely on addAll calling add, but now we are relying on the superclass not changing its implementation in the future. (Use composition and forwarding instead.) Reference
- Subtyping breaks immutability. Immutability is a desirable feature of an ADT. Cannot allow an immutable class to be extended; otherwise subclass could break guarantees made by parent. In Java, making a class final means that it is a compile-time error to extend it. Also, you should make instance variables final even if they are already private. This ensures that they cannot be changed, even using reflection.
- Can't implement equals() correctly.
Interfaces vs. subtyping. Interfaces inherit only constants from an interface, not implementations of methods. Interface hierarchy is independent of class hierarchy. A Java class can implement any number of interfaces (whereas you can only inherit from one superclass).
Sound filters.
Do something with sound filters, e.g., high-pass filter, echo filter, etc.Paint program. Program Paint.java waits for the user to click and drag the mouse, and draws a circle of the user-specified diameter. It uses XOR mode to erase and redraw the circle.
|
|
|
Mandelbrot set. Program MandelbrotZoom.java plots the Mandelbrot set, and then zooms in on the rectangle the user selects. Note that the interface is not very responsive since the user must wait for the whole to be drawn before they can re-zoom. We would need to use "threads" to make the GUI respond instantly.
Picture zoom. Zoom in or zoom out of a photo by clicking the mouse.
Linear regression. Program LeastSquares.java plots points wherever the user clicks, and then draws the least squares fit line through the points after each point is added.
|
|
|
Computational geometry.
Shape super class (or perhaps an interface instead). Rectangle, circle, point, triangle, polygon subclasses.Create random shapes and compute area using Monte Carlo integration.
public abstract class Shape { private Color color; public void setColor(Color c) { color = c; } public Color getColor() { return color; } public abstract void draw(); public abstract double area(); public abstract double perimeter(); }
public static void main(String[] args) { int M = Integer.parseInt(args[0]); // # shapes int N = Integer.parseInt(args[1]); // # samples Shape[] shapes = new Shape[M]; for (int i = 0; i < M; i++) { int r = (int) (Math.random() * 3); if (r == 0) shapes[i] = new Rectangle(); else if (r == 1) shapes[i] = new Circle(); else shapes[i] = new Triangle(); } for (int i = 0; i < M; i++) shapes[i].draw(); for (int j = 0; j < N; j++) { Point p = new Point(); boolean contains = false; for (int i = 0; i < N; i++) { if (shapes[i].contains(p)) contains = true; } if (contains) yes++; } System.out.println("Estimate of area = " + 1.0 * yes / N); }
Voronoi diagram.
Program Voronoi.java plots points wherever the user clicks, and then draws the Voronoi diagram. The Voronoi diagram (and its cousin, the Delaunay triangulation) have numerous applications ranging from anthropology to typography. References: voronoi.com and David Eppstein.
|
|
|
Delaunay triangulation.
Program Delaunay.java plots points wherever the user clicks, and then draws the Delaunay triangulation. The Delaunay triangulation has numerous scientific applications. Perhaps the most important is finite element methods for computational fluid dynamics. Here, a PDE is simulated over a continuous surface, which is decomposed into a mesh of triangular elements. The Delaunay triangulation has many appealing computational properties (triangles are as close to equilateral as possible), and it is efficiently computable. Note also that the boundary is the convex hull.
|
|
|
Pong. Pong is a primitive video game. Pong.java is the beginning of a Java implementation of Pong using Turtle graphics. Ultimately, we should create data types to represent the ball and paddles. We use the images paddle.png, ball.png, and background.png from TomPong. As per the GPL license, here is the original original source code. The original source of the paddle is LBreakout2 and the ball is KBounce. Here is a screen snapshot of the game as it will appear in progress.

GUI widgets. Program Celsius2Fahrenheit.java provides a text field for the user to enter a temperature in degrees Fahrenheit, and converts this to degrees Celsius. (To be replaced by an interesting example....) When the user types enter, this generates an ActionEvent and triggers a callback to the actionPerformed method.
Program ImageProcessor.java illustrates using a pulldown menu in an image processing application. The user can load an image from the file system in JPEG, PNG, or GIF format. Then the user can apply one of several image processing filters to the image. At any time the user can save the current image. We use the JFileChooser library for the open and save dialog boxes. This represents a significant amount of code that we don't want or need to re-implement every time we open a file. Moreover, by always using the built-in widget, we provide the user with a consistent interface. We re-use our Picture.java library for creating the image and accessing the pixels. Its method getJPanel enables us to embed the picture into the frame.
Program Slider.java draws a spirograph. The figure is characterized by three parameters, R, r, and a. The user can adjust the parameter R using a slider, and the figure is drawn as the slider is moved. Program Spirograph.java is a fancier version that provides 3 sliders with labels.
Normal approximation to binomial distribution.
Helper class LabeledSlider.java. Program Binomial.java is a visualization that illustrates the normal approximation to the binomial distribution. Relies on Draw.java and ProbStat.java.
GUI demo. Program GUI.java is a template of an application where the user can click buttons or click and draw points on a map. It uses the image file map.png.
BlackJack. Blackjack is a popular online card game. In a simple version (See the Exercises for more complicated variants), there are two players, the dealer and the gambler. Each player is dealt 2 cards from a standard 52 card deck of cards. The goal is to have a hand value of closer than 21 than the dealer, without going over. (Jacks, queens, and kings count as 10, aces count as 1 or 11, the cards 2 through 9 count as indicated. The suits are irrelevant.) The dealer's strategy is fixed: hit on 16 or below, stand or 17 or above. The gambler has two basic options: to draw another card (hit) or to stop (stick). The gambler is permitted to continue hitting until they exceed 21. The gambler gets to see one of the dealer's cards, and should base their hitting strategy, in part, on this information.
One of the main challenges in designing a computerized Blackjack program is the design. We embrace the OOP paradigm and decompose our program into components representing real world objects. A number of objects spring to mind: an individual playing card, a deck of cards, a player, and the game itself. Our program is organized accordingly.
- Card.java is a data type that represents one of the 52 playing cards. Each Card stores the rank and suit of a single playing card. There are many sensible ways to do this. We choose to maintain two instance variables, suit and rank. The variable suit stores an integer from 0 to 3, representing clubs, hearts, diamonds, and spades, respectively. The variable suit stores an integer from 0 to 12, representing 2, 3, 4, ..., Jack, Queen, King, and Ace. We a toString method to return a text description of the Card and a draw method to draw it using our graphics library. For Blackjack, it is also convenient to have a method isAce to tell us whether the card is an Ace, and a method rank to tell us the Blackjack value of a card. We also include an instance variable isConcealed that stores a boolean value to indicate whether or not the card is face down or face up. We use two helper methods conceal and reveal to set the isConcealed bit.
- Deck.java is a data type that represents a deck of 52 playing cards. The Deck constructor creates a new deck of 52 cards, in sorted order. It has a method shuffle for shuffling the deck, a method size for returning the number of cards left in the deck, and a method get for deleting and returning the top card. As in Section 3.2 we use the library cards.jar to display images of the playing cards.
- Player.java is a data type that represents one of the blackjack players, either the dealer or the gambler. It stores the hand of cards that a player holds. In Blackjack, a player will never have more than 9 cards, but to make the object more general, we enable each Player to hold up to 52 cards. We include a method add to insert a Card, a method reset to discard the hand, and a method value to return the blackjack value of the hand. We make Player extend TurtlePanel so that it has drawing capabilities. Perhaps, a better design would be to have separate Player and PlayerPanel objects.
-
BlackJack.java represents the
game itself, including the GUI. Here is a screen snapshot of the
game in progress.

Q + A
Q. What does a.equals(b) do if a and b are arrays?
A. Same things as (a == b). Use
Arrays.equal(a, b) to check if elements within
the array are equal (rather than just the array references).
Exercises
- Write an interface ComplexFunction that represents a function that takes a complex input and returns a complex number.
- Write subclasses Put and Call of Option.
- Generalize Mandelbrot.java so that you can use it with different update formulas (not just z = z^2 + c) that the user can choose. Be careful about concluding that the point is not in the set when |z| > 2.
- Discrete probability distributions. Create a data type DiscreteDistribution that takes an array of values (that sum to 1) as input. Preprocess (e.g., compute cumulative sums) to make it more efficient. Have methods: sample(), pdf(), cdf(), mean(), variance().
- Continuous probability distribution. Create an interface ContinuousDistribution that supports pdf(), cdf(), sample(), inverseCdf(). Could provide reference implementation of inverseCdf() and sample() in superclass, using binary search to implement inverseCdf().
- Write an interface for twice differentiable functions. Write a client that uses Newton's method to find the root of an arbitrary twice-differentiable function.
- Particle. Create a data type for particle with position, velocity, mass, and charge. Create a subclass Nucleus that contains additional instance variables = number of protons, number of neutrons.
- Molecule. Create a data type for molecules with center of mass. Create a subclass PeptideChain that has the additional method of extracting a subchain.
- Chess pieces. Create a data type for chess pieces. Inherit from the base class Piece and create subclasses Rook, King and so on. Include a method isLegalMove(Position a, Position b) that termines whether the given piece can move from a to b.
- Tetris pieces. Create a data type for Tetris pieces. Inherit from the base class Piece and create subclasses for each of the piece types with implementations for rotate() and drop().
- Matrices.
Why would the following be a bad design decision?
The subclass SymmetricMatrix inherits all of the operations of Matrix, including the one to change the value of entry i-j. If the client did this without changing j-i, it would create a SymmetricMatrix object that did not have symmetric entries.public class SymmetricMatrix extends Matrix { ... } - Shape3D. Create an interface / abstract class for 3D shapes, e.g., volume(), surfaceArea(), sample(), boundingBox3D(), sample(). Then create data types Cylinder, Sphere, Cube.
- Circle extends Point.
Analyze whether the following is an appropriate use of inheritance.
- circle extends point
- point extends circle
-
Write a program to create a resistor network for the following circuits
-
Write a program to create a resistor network for the following circuits
-
Modify the the resistor network data type to support operations involving
getting the potential and power of various components of a circuit
according to Ohm's Law.
- Modify Graffiti.java so the size of the circle is adjusted if the user types the key 0-9.
- Modify Graffiti.java so that the color of the circle changes according to the spectrum.
- Modify Graffiti.java so that each time the user clicks, it draws a circle centered at the current location with the integer i printed in the middle for the ith circle.
- Modify Graffiti.java so it when you click on points, it connects the new one to the previously drawn one with a line segment.
- Modify Graffiti.java so that it saves the graffiti in a file when the user types 's'.
- Write a program ColorMandelbrotZoom.java that plots the Mandelbrot set using a 256 color palette such as mandel.txt, and lets the user zoom in as in MandelbrotZoom.java.
-
Consider the following implementation of the compareTo()
method for String. How does the third line help
with efficiency?
public int compareTo(Object x) { String s = this; String t = (String) x; if (s == t) return 0; int n = Math.min(s.length(), t.length()); for (int i = 0; i < n; i++) { if (s.charAt(i) < t.charAt(i)) return -1; else if (s.charAt(i) > t.charAt(i)) return +1; } return s.length() - t.length(); }Answer: avoid directly comparing all n characters if s and t are references to the same string.
Creative Exercises
- Asteroids. Write a program Spaceship.java that lets the user rotate and accelerate a spaceship, as in the game of Asteroids. When the user type 'j' or 'l' the spaceship should rotate 2 degrees counterclockwise or clockwise. When the user type 'i' or 'k' the spaceship should accelerate in the current direction. Use periodic boundary conditions to ensure that the spaceship always remains visible. Use the image starfield.jpg for the background and starship.gif for the spaceship.
- Sokoban. Implement the Japanese game of Sokoban. Use arrows keys to move the porter. Include an undo feature.
- Capacitor networks. Write a superclass CapacitorNetwork and subclasses Capacitor, Parallel, and Series to build up a capacitor network. Works exactly like resistor networks, except rules for series and parallel and reversed.
- Slider puzzle.
Write a program that chooses 8 of the 9 images
slider1.gif through slider9.gif and arranges
them in a 3-by-3 grid with one blank tile blank.gif.
If the user clicks a tile and it is adjacent to
the empty tile, "slide" that tile to the empty square and
play a sound effect.

- 15-slider puzzle. Write a program that prints 15 tiles labeled 1 through 15 in a 4-by-4 grid. If the user clicks a tile and it is adjacent to the empty tile, "slide" that tile to the empty square and play a sound effect.
- Pong with multiples balls. Modify Pong.java so that there are three simultaneous balls.
- Pong with spin. Modify Pong.java so that if the ball strikes the paddle while the paddle is moving, the ball spins according to the laws of physics.
- Blackjack. Redo where the user types H for hit, S for stick, and D for deal. Use Turtle graphics.
- Blackjack variants.
- Use 4 decks instead of one.
- Keep track of the number of times the player has won and lost, and print out the results after each game.
- Add a button that allows the player to place 1, 2, or 4 dollar bets on each hand.
- If the gambler gets 21 with two cards (blackjack), then she wins 1.5 times her bet. A natural blackjack beats a 21 obtained with three or more cards.
- Allow the gambler to double down: if the gambler has exactly two cards, then the gambler can double the size of the bet if she agree to receive exactly one additional card.
- Allow the gambler to buy insurance if the dealer's face up card is an ace.
- Allow the gambler to surrender: before making any other decisions, the gambler can fold her cards, and receive half her bet back.
- Allow the gambler to split pairs: if the gambler's two initial cards are the same (ignoring the suits), she can split the hand into two individual hands, and play them independently.
- Blackjack strategy. Create an automated strategy for the gambler and see how well it does by playing a million hands. (You'll probably want to lose the GUI for this type of experiment.) Use the basic strategy. By counting cards, you may be able to win money consistently. If your program does so, plan a trip to Las Vegas.
- Poker. Write a program that evaluates 5 card poker hands and prints out the best hand according to the standard order: royal flush, straight flush, four of a kind, full house, flush, straight, three of a kind, two pair, one pair, high card. If there is a tie, a pair of 8's beats a pair of 7's, etc.
- Five of a kind. Suppose you add a joker that acts as a wild card in five card poker. Determine mathematically whether a royal flush should beat five of a kind or vice versa. Repeat if you add two jokers.
- Texas Hold 'Em. Texas Hold 'Em is a popular variant of poker. Before each hand, the dealer shuffles a standard 52 card deck. The dealer deals two cards face down (the hole cards) to each player. Then, the dealer deals five cards face up (the communal cards) in the middle of the table. Each player selects their best 5 card hand from the hole cards and the communal cards. Write a program to determine the best hand given two hole cards and five communal cards.
- World Series of Poker. The World Series of Poker is played using Texas Hold 'Em. There is a round of betting after the first three communal cards (the flop) are dealt, and then again after the fourth communal card (the turn card), and again after the fifth communal card (the river card). ESPN televises the event and displays the probability that each hand will win after the flop, based on knowledge of every player's hole cards and the flop. Write a program to determine the exact probabilities by enumerating over all pairs of possible turn and river cards.
- Moving circle. Write a program that draws a circle. It moves left, right, up, or down, if the user types the corresponding key. It changes color to red, green, or blue if the user types 'r', 'g', or 'b'.
- Coordinates. Modify Graffiti.java so that it writes the (x, y) coordinate of each mouse click to the screen, centered at the location (x, y) of the mouse click.
- Paint. Modify Graffiti.java so that it changes the color to red, green, or blue if the user types 'r', 'g', or 'b'. Also, have it change shapes from square to circle if the user types 's' or 'c'. Change the diameter of the circle or square if the user types '1' (small) through '9' (large).
- Concentration. Implement the game of concentration. There is an N-by-N grid of cards, displayed face down. The user selects two of them to reveal. If they match, then the two cards are removed from the grid. Otherwise, the user is charged with 1 point and the cards are concealed. Repeat until the board is cleared.
- Minesweeper. Implement the game of Minesweeper.
- Tic-tac-toe. Implement the game of tic-tac-toe with two human players (or one human and one computer player).
Resistor networks.
When electricity moves through a wire, it is subject to electrical friction or resistance. When a resistor with resistance R is connected across a potential difference V, Ohm's law asserts that it draws current I = V / R and dissipates power V^2 / R. A network of resistors connected across a potential difference behaves as a single resistor, which we call the equivalent resistance. The simplest way to connect more than resistor network is to use one of the following two composition rules. Each leads to a particularly simple formula for computing the equivalent resistance of the resulting network.- Series: Connect two resistor networks end-to-end in a single chain. If the equivalent resistance of the two networks are R1 and R2, then the equivalent resistance of the combined network is given by additive rule: R1 + R2. Ex: old Christmas lights - if one burns out, then it would break circuit and all other lights would go out.
- Parallel: Connect two resistor networks in parallel.
If the equivalent resistance of the two networks are
R1 and R2, then the equivalent resistance of the
combined network is given by the reciprocal rule:
1 / (1/R1 + 1/R2).
Parallel (e.g., electrical wiring in homes so that you can
turn on lights independently).
The resistors R2 and R3 and connected in series, so we apply the series formula to them to get a total resistance of R2 + R3. This total resistance is shown in the black box, which is connected in parallel with resistor R1. Now apply the parallel formula to R1 and the box, obtaining the circuit's resistance, 1 / (1/R1 + 1/(R2+R3)).
However, not all resistor networks are series-parallel networks, e.g., a bridge with 5 resistors. In these cases, we need to use a more powerful technique known as Kirchoff's method (see section xyz).
To create series-parallel resistor networks in Java, we define a superclass Circuit.java that encapsulates the basic properties of a resistor network. For now, each network has a method resistance that returns the equivalent resistance of the circuit.
A series-parallel resistor network is either (i) a single resistor or (ii) built up by connecting two resistor networks in series or parallel. We create three subclasses Resistor.java, Series.java, and Parallel.java. Our goal is to be able to compose circuits as in the following code fragment, which represents the circuit depicted below.
public abstract class Circuit { public abstract double resistance(); }
Circuit a = new Resistor(3.0); Circuit b = new Resistor(3.0); Circuit c = new Resistor(6.0); Circuit d = new Resistor(3.0); Circuit e = new Resistor(2.0); Circuit f = new Series(a, b); Circuit g = new Parallel(c, d); Circuit h = new Series(g, e); Circuit circuit = new Parallel(h, f); double R = circuit.resistance();
- The class Resistor contains a constructor which sets
the resistance in Ohms and an accessor method to return it.
public class Resistor extends Circuit { private double resistance; public Resistor(double r) { resistance = r; } public double resistance() { return resistance; } } - The class Series contains a constructor which takes
two resistor circuit objects as inputs and represents a circuit
with the two components in series.
public class Series extends Circuit { private Circuit a; private Circuit b; public Series(Circuit a, Circuit b) { this.a = a; this.b = b; } public double resistance() { return a.resistance() + b.resistance(); } } - The class Parallel is almost identical to Series
except that it uses the reciprocal rule instead of the additive rule
to compute the equivalent resistance.
public double resistance() { double R1 = a.resistance(); double R2 = b.resistance(); return 1.0 / (1.0 / R1 + 1.0 / R2); }
Electricity moving through a wire is comprised of
voltage (V), current (I), and resistance (R).
The resistance measures the electrical friction.
Ohm's law relates the three quantities
by the famous formula V = I * R.
When a battery is attached to a circuit, it creates a
"potential difference" across the circuit. Smaller potential
differences are created across each circuit segment. The potential
difference across each section depends on whether the
circuit is series or parallel. For a parallel circuit, the potential
difference across each branch is equal to the potential
difference across the whole parallel circuit.
For a series circuit, first find the current (I) from Ohm's law I = V/R,
where V is the potential difference across the series circuit and R is
its total resistance. The potential difference across each resistor is
equal to the current times the resistance of that resistor.
