Assignment 8, due Mar 24Solutions
Part of
the homework for CS:2820, Spring 2017
|
On every assignment, write your name and section number. Write your name as it appears on your university ID card! Use the section number as it appears in your current registration! We will not do detective work to figure out who did what. Homework is due on paper at the start of your discussion section. Exceptions will be made only by advance arrangement with your TA (excepting "acts of God"). Never push homework under someone's door!
a) The error message says that some variable cannot be accessed when calling the constructor new Event(). What variable? (0.4 points)
The variable is this in Simulation.schedule().
Here is the error message you get; note that because the word this is not in quotes, it is easy not to read it as a variable name. This problem with readability leads the reader to ask "this what?"
RoadNetwork.java:139: error: non-static variable this cannot be referenced from a static context eventSet.add( new Event( time, act ) ); ^ 1 error
To explain this error in more detail, the constructor Event(time,act) has two explicit parameters, and if class Event is not static, it also has an implicit parameter, the object of class Simulation within which a new Event is being constructed. If Simulation.schedule() was not static, then this would refer to an object of class Simulation. Because Simulation.schedule() is static, this is undefined so we get the error message shown above.
b) The variable in question is passed as an implicit parameter to the constructor. In this case, the parameter is never needed. There are three reasons for this, any one of which is sufficient. Give them. (Hint: All of them are negative reasons -- that is, thing that are not present or that the program never does and each can be expressed in a short sentence.) (0.6 points -- 0.2 for each reason)
First, no instances of class Simulation are ever created.
Second, class Simulation does not contain any non-static fields or methods, so even if an instance of Simulation was created, there is no way that any code in class Event could atempt to reference them.
Third, even if an object of class Simulation was created and even if it contained non-static fields or methods, none of the code within class Event refer to any fields or methods of class Simulation.
In effect, source code examination allows us to talk about an inner class being effectively static despite not being tagged with the static keyword. The Java compiler doesn't notice this, although it does have a concept of a variable being effectively final.
a) Write the code for the addIncoming() method in class Gate, along with any new fields of class Gate that this requires. Do not write comments, but please indent your answer properly. (0.5 points)
Here is a simple solution:
private int incount = 0; // wires as they are connected to this gate public addIncoming() { incount = incount + 1; }
And here is a more complicated but perhaps more obvious solution: Here is a simple solution:
private final LinkedListincoming = new LinkedList (); public addIncoming( Wire w ) { incoming.add( w ); }
The second solution may be overkill, because for sanity checking, the only thing we do with the list incoming is check its size.
b) Write the code for the check() method in class Gate that works with your code above plus the existing code of the class. Do not write comments, but please indent your answer properly. (0.5 points)
Here is the simple solution; the solution that works with the more complicated solution above is obvious enough that it isn't given here:
public void check() { if (incount != inputs) { Errors.warn( this.toString() + " improper number of inputs" ) } }
It might be better to divide the warning into one saying "too many inputs" and one saying "too few inputs", but for the purpose of this question, this suffices.
Why no comments above? Because these answers are so short that comments will just slow us down when we read them. In the context of a whole program, they probably do need, at the bare minimum, header comments.
Assume that class Gate is augmented with the following new fields:
a) Write the code for Wire.inputChange(). This is fairly simple, since all it does is schedule a corresponding output change after the wire's delay. (0.5 points)
public void inputChange( float time, int old, int new ) { Simulation.schedule( time + delay, (float t) -> outputChange( t, old, new ) ); }
b) Write the code for MinGate.inputChange(). This is harder because it has to determine whether the output should change. Suggestion: Update inputCounts after each input by decrementing the array entry for the old value and incrementing the entry for the new value. Then compute the new output value as the minimum array index for which the array entry is nonzero. Finally, if the new output value differs from output, schedule an output change and update the value of output. (0.5 points)
public void inputChange( float time, int old, int new ) { inputCounts[old]--; inputCounts[new]++; int newOutput = 0; while (inputCounts[newOutput] == 0) newOutput++; if (output != newOutput) { final int old = output; final int new = newOutput; Simulation.schedule time + delay, (float t) -> outputChange( t, old, new ) ); output = newOutput; } }
The one tricky thing in this code is the pair of final variables in the inner block. You'd think you could write this lambda expression without needing those two variables:
(float t) -> outputChange( t, output, newOutput )
The problem is, Java demands that the variables referenced from within a lambda expression be "final or effectively final". In the case of output, it is obviously not final because the immediate next thing done in the code is to assign a new value to output. When the lambda expression's body is eventually evaluated, we want it to use the old value of output and not the value that is about to be changed. Thus, we really do need a copy of this value. In the case of newOutput is is, in fact, effectively final because no further changes in its value will take place after the while loop terminates. The Java compiler, however, may not be smart enough to figure this out.