In the section of "Adapting to an interface", page 238 of "T开发者_StackOverflow中文版hinking in Java", author introduces the following example
public class RandomDoubles {
private static Random rand = new Random(47);
public double next() { return rand.nextDouble();}
public static void main(string[] args){
RandomDouble rd = new RandomDoubles();
for (int i=0; i<7; i++)
System.out.print(rd.next()+" ");
}
}
Associated with this example, the author states
Suppose you have a class that does not already implement Readable(interface)-how do you make it work with Scanner(class)?
Because you can add an interface onto any existing class in this way, it means that a method that takes an interface provides a way for any class to be adapted to work with that method. This is the power of using interfaces instead of classes.
However, I do not quite understand how this statement is reflected in the example. For instance, where does the interface added? What does the method in "method that takes an interface" refer to?
I would go as far as to say that the given text is not associated with the code fragment you provided.
Text
The text describes the use of an interface (which RandomDoubles is not, as far as I can tell), specifically Readable. I'm not intricately familiar with the way the Scanner works, as I've been out of Java for some time recently.
However, Scanner may take a Readable object as a parameter, which it then reads from. What this means is that somewhere in Scanner/read, code like the following appears.
Readable object = (parameter that is an object that implements Readable);
...
//in Scanner.read
object.read(buffer);
That Readable object can be one of any of the classes that implement Readable, either a custom class of your own, or a FileReader, BufferedReader, InputStreamReader...
Because those classes implement Readable and thereby must define read(buffer), they can be used interchangably in the Scanner class by referring to them as an object of that Interface type.
The text specifically mentions that you can add that functionality to any existing class by making it implement Readable and then defining how its read(buffer) method would output characters into a buffer.
Code Fragment
The code fragment attached simply specifies a way that a custom class can use a Random object, but only expose its ability to generate random doubles to any program using that class. This is not related to interfaces.
//Jim Colmenero - Application Architect - colmeneroj@videotron.ca
//It's been a while, but quite easy really.
import java.nio.CharBuffer;
import java.util.Random;
import java.util.Scanner;
public class RandomDoubles implements Readable{
private static final long seed = 47;
private static Random randomNbrGenerator = new Random(seed);
private int count; // you just want 5 doubles printed
public RandomDoubles(int count) { // ctor
this.count = count;
}
public int read(CharBuffer cb) {
if (count-- == 0)
return -1; // Indicates end of input
cb.append(Double.toString(randomNbrGenerator.nextDouble()));
cb.append(" ");
return 0; // Number of characters appended- any positive value for this example
}
public static void main(String[] args) {
Scanner scanner = new Scanner( new RandomDoubles(5) );
while (scanner.hasNext()) {
System.out.println(scanner.next());
}
}
}
// Output:
0.7271157860730044
0.5309454508634242
0.16020656493302599
0.18847866977771732
0.5166020801268457
Process finished with exit code 0
===================================================================================
Now, another way to answer the question, is NOT TO TOUCH the original code of the
RandomDoubles class, but instead add and execute an Adapter class like so:
import java.nio.CharBuffer;
import java.util.Scanner;
public class AdapterRandomDoubles
extends RandomDoubles
implements Readable {
private int numberOfDoubleValues;
public AdapterRandomDoubles(int numberOfDoubleValues) { // ctor
this.numberOfDoubleValues = numberOfDoubleValues;
}
public int read(CharBuffer cb) {
if (numberOfDoubleValues-- == 0)
return -1; // Indicates end of input
cb.append(Double.toString(nextRandomNbr()));
cb.append(" ");
return 0;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(new AdapterRandomDoubles(5)); // 5 random numbers
while (scanner.hasNext())
System.out.println(scanner.next());
}
}
==== I guess that's it for now. So remember, debug to get the hang of it and have fun
==== like I do.
In solution,
replace line: cb.append(Double.toString(nextRandomNbr()));
with line: cb.append(Double.toString(next()));
精彩评论