20-CS-694 | Advanced Programming Techniques | Spring 2012 |
---|---|---|
Exceptions for control |
Add Up Exception for control
The interface Variable has changed: its checkit()
method no longer returns a boolean and, instead, throws an
Up exception. Accordingly, the Up class is defined,
without state, to extend the Exception class. The
checkit() method catches an Up exception from its
Choose object: this is what keeps the loop going until it
ends and, when that happens, checkit() throws an Up
to the next higher level. By using Up we can define method
assert_() in the Evaluate class: if an expression
evaluates to 0 (false), an Up is thrown by
assert_(). This allows all control statements to be removed
from checkit() in Evaluate which is significant
because, except for solve(), that is the method that a user
will have to change for every different problem this approach is going
to be used to solve.
Two improvements can be made right away to the code below. If we only want one result instead of all results we can define an Out exception class and raise that exception when a solution is found. The Out object will then be passed right up to the top, bypassing all the intermediate catch blocks which are looking for Up exceptions. The second improvement is to remove the v() and abstract_() methods from the Evaluate class. The abstract_() method will be needed to solve any problem like this so let's put it in a Puzzle class and extend from that. We might as well put the v() in there too to get it out of the way. This is done on the next slide.
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.applet.*; interface Variable { void checkit() throws Up; int v(); } class Up extends Exception { } class Choose implements Variable { Variable next_for; int val = 0; Choose (Variable next_for) { this.next_for = next_for; } public void checkit () throws Up { for ( ; val < 2 ; val++) try { next_for.checkit(); } catch (Up up) { } val = 0; throw new Up(); } public int v() { return val; } } class Evaluate implements Variable { Variable i,j,k; D problem; public Evaluate (D problem) { this.problem = problem; problem.out.append("\nSolve: ((1-i)*j + i*(1-k) + (1-j)*k)\n\n"); } public void assert_ (boolean e) throws Up { if (!e) throw new Up(); } public void checkit() throws Up { assert_((((1-i.v())*j.v()+i.v()*(1-k.v())+(1-j.v())*k.v()) % 2) == 1); problem.out.append("i="+i.v()+" j="+j.v()+" k="+k.v()+"\n"); throw new Up(); } public void solve () { try { k = new Choose(this); j = new Choose(k); i = new Choose(j); i.checkit(); } catch (Up up) {} } public int v() { return 0; } } public class D extends Applet implements ActionListener { JTextArea out; JButton button; public void init () { setLayout(new FlowLayout()); add(new JScrollPane(out = new JTextArea(16,30))); add(button = new JButton("Press Me")); button.addActionListener(this); } public void doit() { Evaluate eval = new Evaluate(this); eval.solve(); } public void actionPerformed (ActionEvent evt) { doit(); } }
|