Objectbased Scanning Redo the scanning solution Monolithic single
Object-based Scanning • Redo the scanning solution • Monolithic, single class solution – does UI and scanning • No reuse of code • Another scanning problem to show reuse.
Scanning Problem
Upper case printing package warmup; public class An. Upper. Case. Printer { public static void main(String[] args){ if (args. length != 1) { System. out. println("Illegal number of arguments: " + args. length + ". Terminating program. "); System. exit(-1); } System. out. println("Upper Case Letters: "); int index = 0; while (index < args[0]. length()) { if (is. Upper. Case(args[0]. char. At(index))) System. out. print(args[0]. char. At(index)); index++; } } System. out. println(); } public static boolean is. Upper. Case(char c) { return (c >= 'A') && (c <= 'Z'); } }
Printing Scanned Characters Backwards Cannot scan multiple times
Strings = Char Sequences String {sequences of characters} J o h n h e l l F o . 1 K 4 3 l e n 0 n e d y
Other Sequences as Predefined Types Int. Sequence 100 {sequences of integers} 98 99 100 90 80 60 40 50 Double. Sequence {sequences of doubles} 3. 8 3. 1 3. 7 String. Sequence JFK FDR JC 3. 1 3. 6 3. 9 {sequence of Strings} BC RR GB
Other Sequences as Array Types int[] 100 {sequences of integers} 98 99 100 90 80 60 40 50 double[] 3. 8 3. 1 {sequences of doubles} 3. 7 String[] JFK FDR JC 3. 1 3. 6 3. 9 {sequence of strings} BC RR GB
Initializing Array Declarations Array Type Element Type int[] assignment. Scores = {100, 98, 99, 80}; assignment. Scores 100 98 99 100 90 80 Array Literal Array Variable double[] gpas = {3. 8, 3. 1, 3. 7, 3. 1, 3. 6, 3. 9}; 3. 8 3. 1 3. 7 3. 1 3. 6 3. 9 String[] initials = {“JFK”, “FDR”, “JC”, “BC”, “GW”, “WW”}; JFK FDR JC BC GW WW
Array Operations String[] initials = {“JFK”, “FDR”, “JC”, “BC”, “GW”, “WW”}; HT JFK FDR JC BC GW WW public named constant initials. length 6 initials[0] Array Instance Size Fixed initials[initials. length - 1] initials[initials. length] Array. Index. Out. Of. Bounds. Exception initials[0] = “HT” initials[initials. length] = “HT” Array. Index. Out. Of. Bounds. Exception
Array Types have Variable-Size int[] 100 98 99 100 90 80 60 40 50 int[] assignment. Scores = {100, 98, 99, 100, 99, 80}; assignment. Scores = {60, 40, 50}; assignment. Scores 10040 98 60 50 99 100 90 80
Uninitializing Array Declaration int[] assignment. Scores; assignment. Scores = {60, 40, 50}; assignment. Scores 60 40 50 null
Array Elements Uninitialized int[] assignment. Scores = new int[3]; assignment. Scores 0 0 0
Printing Scanned Characters Backwards
Variable-Size Collection unfilled part filled current part size maximum size
Variable-Size Collection size 3 array J F filled part K current size maximum size unfilled part
Variable-Size Collection static final int MAX_CHARS = 7; static char[] upper. Case. Letters = new char [MAX_CHARS]; static int number. Of. Upper. Case. Letters = 0;
Solution package warmup; public class AReverse. Upper. Case. Printer { static final int MAX_CHARS = 5; static char[] upper. Case. Letters = new char[MAX_CHARS]; static int number. Of. Upper. Case. Letters = 0; public static void main(String[] args){ if (args. length != 1) { System. out. println("Illegal number of arguments: " + args. length + ". Terminating program. "); System. exit(-1); } int index = 0; System. out. println("Upper Case Letters: "); while (index < args[0]. length()) { if (is. Upper. Case(args[0]. char. At(index))) { System. out. print(args[0]. char. At(index)); store. Char(args[0]. char. At(index)); } index++; } System. out. println(); print. Reverse();
Solution (contd. ) public static void store. Char(char c) { if (number. Of. Upper. Case. Letters == MAX_CHARS) { System. out. println("Too many upper case letters. Terminating program. "); System. exit(-1); } upper. Case. Letters[number. Of. Upper. Case. Letters] = c; number. Of. Upper. Case. Letters++; } public static void print. Reverse() { System. out. println("Upper Case Letters in Reverse: "); for (int index =number. Of. Upper. Case. Letters - 1; index >= 0; index--) { System. out. print(upper. Case. Letters[index]); } } }
No reuse in Monolithic Solutions int index = 0; System. out. println("Upper Case Letters : "); //token processing while (index < args[0]. length()) { if (Character. is. Upper. Case(args[0]. char. At(index); )) System. out. print(args[0]. char. At(index)); // token processing index++; } int index = 0; System. out. println("Upper Case Letters : "); //token processing while (index < args[0]. length()) { if (Character. is. Upper. Case(args[0]. char. At(index); )) { System. out. print(args[0]. char. At(index); ); // token processing store. Char(args[0]. char. At(index)); } index++; }
Class Decomposition? Main Class
Division of Labor in Radio Scanning
Division of Labor in Radio Scanning
Division of Labor in Radio Scanning
Division of Labor in Radio Scanning
Division of Labor in Radio Scanning
Division of Labor in Radio Scanning
Division of Labor in Radio Scanning
Division of Labor in Radio Scanning ?
Division of Labor in Radio Scanning
Class Decomposition Scanner Class instantiate Scanner Object calls Scanner User Main Class (Input & Output)
Class Decomposition instantiate Buffered. Reader Instance read. Line() Scanner User Main Class (Input & Output)
Scanner User-Scanner Object Interaction Buffered. Reader data. In = new Buffered. Reader (new Input. Stream. Reader( System. in)); int product = 1; // add input list terminated by a negative number while (true) { int num = Integer. parse. Int (data. In. read. Line()); if (num < 0) break; product = product*num; } System. out. println (product);
Constructor parameters • Input. Stream. Reader takes System. in as parameter. • Buffered. Reader takes Input. Stream. Reader as parameter. • In general, scanner takes object producing scanned stream as parameter.
Buffered. Reader Operations Line 1 Line 2 data. In. read. Line() Line 1 data. In. read. Line() Line 2 data. In. read. Line() IOException Multi-line input stream Line stream
Scanner Interface? Input stream token 1 token 2 scanner. next. Element() token 1 scanner. next. Element() token 2 scanner. next. Element() Scanner. Exception Token Stream
Scanner Interface? Input stream token 1 token 2 scanner. next. Element() token 1 scanner. next. Element() token 2 scanner. has. More. Elements() scanner. next. Element() false ? ? ? Token Stream
Uppercase Scanner Interface? J o token 1 h n F . token 2 K token 3 scanner. next. Element() ‘J’ scanner. next. Element() ‘F’ scanner. next. Element() ‘K’ scanner. has. More. Elements() scanner. next. Element() e false ? ? ? n n e d y
Enumeration Interfaces package enums; public interface Char. Enumeration { public char next. Element(); public boolean has. More. Elements(); } package enums; public interface String. Enumeration { public String next. Element(); public boolean has. More. Elements(); } package <P>; public interface <Type>Enumeration { public <Type> next. Element(); public boolean has. More. Elements(); }
Using an Enumeration Interface J o token 1 h n F . token 2 K e n n e d y token 3 public static void print. Chars (Char. Enumeration char. Enumeration) { while (char. Enumeration. has. More. Elements()) System. out. print(char. Enumeration. next. Element()); }
Using an Enumeration Interface package main; import enums. Char. Enumeration; import enums. An. Upper. Case. Enumeration; public class Upper. Case. Printer { public static void main (String args[]) { if (args. length != 1) { System. out. println("Illegal number of arguments: " + args. length + ". Terminating program. "); System. exit(-1); } print. Upper. Case(args[0]); } public static void print. Upper. Case(String s) { System. out. println("Upper Case Letters: "); print. Chars (new An. Upper. Case. Enumeration(s)); } public static void print. Chars (Char. Enumeration char. Enumeration) { while (char. Enumeration. has. More. Elements()) System. out. print(char. Enumeration. next. Element()); }
Implementing Scanner package enums; public class An. Upper. Case. Enumeration implements Char. Enumeration { … public An. Upper. Case. Enumeration(String the. String) {. . . } public boolean has. More. Elements() {. . . } public char next. Element() {. . . ; } … }
Data Structure: Scanned String package enums; public class An. Upper. Case. Enumeration implements Char. Enumeration { String string; … public An. Upper. Case. Enumeration(String the. String) { string = the. String; . . . } public boolean has. More. Elements() {. . . } public char next. Element() {. . . ; } … }
Data Structure: marker string J o h n F . scanned part K e n Unscanned part next. Element. Pos is global rather than loop variable n e d y
has. More. Elements() string J o h n F . next. Element. Pos public boolean has. More. Elements() {. . . } true K e n n e d y
has. More. Elements() string J o h n F . K e n n e d y next. Element. Pos public boolean has. More. Elements() {. . . } true
has. More. Elements() string J o h n F . K e n n e d y next. Element. Pos public boolean has. More. Elements() {. . . } false
has. More. Elements() string J o h n F . K e n n e d y next. Element. Pos //return true if next. Element. Pos is beyond end of string; false otherwise public boolean has. More. Elements() {. . . }
has. More. Elements() string J o h n F . K e n n e d y next. Element. Pos //return false if next. Element. Pos is beyond end of string; true otherwise public boolean has. More. Elements() { return next. Element. Pos < string. length(); }
next. Element() string J o h n F next. Element. Pos public char next. Element() { } . K e n n e d y
next. Element() string J o h n F . K e n n e d next. Element. Pos //Assume next. Elem. Pos is at start of next token or end of string when //method is called. //Method makes sure this is also true before returning. //returns next element if one exists public char next. Elements() { } y
next. Element() string J o h n F . K e n n e d Unexecuted Loop next. Element. Pos //Assume next. Elem. Pos is at start of next token or end of string when //method is called. //Method makes sure this is also true before returning. //returns next element if one exists public char next. Element() { char ret. Val = string. char. At(next. Elem. Pos) while (!is. Upper. Case(string. char. At(next. Element. Pos))) } next. Elem. Pos++; return ret. Val; y
next. Element() string J o h n F . K e n n e d next. Element. Pos //Assume next. Elem. Pos is at start of next token or end of string when //method is called. //Method makes sure this is also true before returning. //returns next element if one exists public char next. Elements() { char ret. Val = extract. Token(); move. Past. Current. Token(); skip. Non. Token. Characters(); return ret. Val; } y
next. Element() string J o h n F . K e n n e d next. Element. Pos //Assume next. Elem. Pos is at start of next token or end of string when //method is called. //returns next token if one exists public char extract. Token() { return string. char. At(next. Element. Pos); } y
move. Past. Current. Token() string J o h n F . K e n n e d next. Element. Pos //Assume next. Elem. Pos is at start of next token or end of string when //method is called. //Moves past current token. public void move. Past. Current. Token() { next. Elem. Pos++; } y
skip. Non. Token. Characters() string J o h n F . K e n n e d next. Element. Pos String. Index. Out. Of. Bounds // keep advancing next. Element. Pos until we hit the next upper case public void skip. Non. Token. Characters() { while (! is. Upper. Case(string. char. At(next. Element. Pos))) next. Elem. Pos++; } y
skip. Non. Token. Characters() string J o h n F . K e n n e d y next. Element. Pos short-circuit String. Index. Out. Of. Bounds? // keep advancing next. Element. Pos until we hit the next upper case or go // beyond the end of the string. public void skip. Non. Token. Characters() { while (next. Element. Pos < string. length() && !Character. is. Upper. Case(string. char. At(next. Element Pos))) next. Elem. Pos++; }
Initialization string j o h n F . K e n next. Element. Pos String string; int next. Element. Pos = 0; public An. Upper. Case. Enumeration(String the. String) { string = the. String; skip. Non. Token. Characters(); } n e d y
Complete Scanner package enums; public class An. Upper. Case. Enumeration implements Char. Enumeration { String string; constructor int next. Element. Pos = 0; public An. Upper. Case. Enumeration(String the. String) { string = the. String; skip. Non. Token. Characters(); } public boolean has. More. Elements() { return next. Element. Pos < string. length(); } public char next. Element() { char ret. Val = extract. Token(); move. Past. Current. Token(); skip. Non. Token. Characters(); return ret. Val; } void move. Past. Current. Token() {next. Element. Pos++; } void skip. Non. Token. Characters() { while (next. Element. Pos < string. length() && !is. Upper. Case(string. char. At(next. Element. Pos))) next. Element. Pos++; } char extract. Token() { return string. char. At(next. Element. Pos); } boolean is. Upper. Case (char c) { return c >= ‘A’ && c <= ‘Z’; }
Scanner Pattern package <P>; public class <Scanner Name> implements <T>Enumeration { String string; int next. Element. Start = 0; int next. Element. End = ? ? ? ; public An. Upper. Case. Enumeration(String the. String) { string = the. String; skip. Non. Token. Characters(); } public boolean has. More. Elements() { return next. Element. Start < string. length(); } public <T> next. Element() { <T> ret. Val = extract. Token(token. Length); move. Past. Current. Token(token. Length); skip. Non. Token. Characters(); return ret. Val; } void move. Past. Current. Token() {…}; void skip. Non. Token. Characters() {…}; char extract. Token() { …} }
Class Decomposition instantiate An. Upper. Case. Enumeration instance An. Uppercase. Printer
Class Decomposition instantiate An. Upper. Case. Enumeration instance AReverse. Upper. Case. Printer
Reuse of Enumeration while (char. Enumeration. has. More. Elements()) { char next. Char = char. Enumeration. next. Element()); System. out. print(next. Char); store. Char(next. Char); } while (char. Enumeration. has. More. Elements()) System. out. print(char. Enumeration. next. Element());
Enumeration vs. Scanning J o token 1 h n F . token 2 K e n n token 3 public interface Char. Enumeration { public char next. Element(); public boolean has. More. Elements(); } e d y
Enumeration without Scanning All. Uppercase. Letters. In. Order ‘A’ ‘B’. . . ‘Z’ implements public interface Char. Enumeration { public char next. Element(); public boolean has. More. Elements(); }
Enumerating all Uppercase Letters //instance variables ? ? ? public char next. Element() { ? ? ? } public boolean has. More. Elements() { ? ? }
Enumerating all Uppercase Letters package enumerations; public class All. Upper. Case. Letters. In. Order implements Char. Enumeration { char next. Letter = 'A'; public boolean has. More. Elements() { return next. Letter <= 'Z'; } public char next. Element() { char ret. Val = next. Letter; next. Letter = (char) (next. Letter + 1); return ret. Val; } }
Comparing Two Implementations J o token 1 h n F . token 2 K e n n e d token 3 An. Upper. Case. Enumeration implements public interface Char. Enumeration { public char next. Element(); public boolean has. More. Elements(); } ‘J’ ‘F’‘K’ y
Radically Different Behaviors Polymorphism print (new An. Uppercase. Enumeration(s)); print (new All. Uppercase. Letters. In. Order()); All. Uppercase. Letters. In. Order ‘A’ ‘B’. . . ‘Z’ implements public interface Char. Enumeration { Syntactic public char next. Element(); Specification! public boolean has. More. Elements(); }
Forward and reverse printing package main; import enums. Char. Enumeration; import enums. An. Upper. Case. Enumeration; public class AReverse. Upper. Case. Printer { static final int MAX_CHARS = 5; static char[] upper. Case. Letters = new char[MAX_CHARS]; static int number. Of. Upper. Case. Letters = 0; public static void main(String[] args){ if (args. length != 1) { System. out. println("Illegal number of arguments: " + args. length + ". Terminating program. "); System. exit(-1); } print. And. Store(args[0]); print. Reverse(); }
Forward and reverse printing public static void print. And. Store (String s) { System. out. println("Upper Case Letters: "); print. And. Store (new An. Upper. Case. Enumeration(s)); } public static void print. And. Store (Char. Enumeration char. Enumeration) { while (char. Enumeration. has. More. Elements()) { char input. Char = char. Enumeration. next. Element(); System. out. print (input. Char); store. Char(input. Char); } System. out. println(); }
Forward and reverse printing (contd. ) public static void store. Char(char c) { if (number. Of. Upper. Case. Letters == MAX_CHARS) { System. out. println("Too many upper case letters. Terminating program. "); System. exit(-1); } upper. Case. Letters[number. Of. Upper. Case. Letters] = c; number. Of. Upper. Case. Letters++; } public static void print. Reverse() { System. out. println("Upper Case Letters in Reverse: "); for (int index =number. Of. Upper. Case. Letters - 1; index >= 0; index--) { System. out. print(upper. Case. Letters[index]); } } }
Remaining problems package main; import enums. Char. Enumeration; import enums. An. Upper. Case. Enumeration; public class AReverse. Upper. Case. Printer { static final int MAX_CHARS = 5; static char[] upper. Case. Letters = new char[MAX_CHARS]; static int number. Of. Upper. Case. Letters = 0; public static void main(String[] args){ if (args. length != 1) { System. out. println("Illegal number of arguments: " + args. length + ". Terminating program. "); System. exit(-1); } print. And. Store(args[0]); print. Reverse(); }
Remaining Problems • Main class does storing • Non UI code • Array, size, and max size closely coupled to each other • Should be in separate class
Variable-Size Collection size 3 array J F filled part K current size maximum size unfilled part
Variable-Size Collection public class <Class. Needing. Variable. Size. TCollection> { … final static T A_MAX_SIZE = 50; T[] a = new T [MAX_SIZE]; int a. Size = 0; … //process a for (int index = 0; index < a. Size; index++) System. out. println(a[index]); … final int B_MAX_SIZE = 50; T[] b = new T [MAX_SIZE]; int b. Size = 0; //process b … }
Special Type public class <Class. Needing. Variable. Size. Collection> {. . . AVariable. Size. TCollection a, b = new AVariable. Size. TCollection(); . . . Constraints violated for (int index = 0; index < a. size; index++) System. out. println(a. contents[index]); … a. size = 0; AVariable. Size. TCollection b = new AVariable. Size. TCollection(); . . . No encapsulation! } public class AVariable. Size. TCollection { public static final int MAX_SIZE = ? ? ? ; public T[] contents = new T [MAX_SIZE]; public int size = 0; }
Supporting Encapsulation package collections; public interface …. { public static final int MAX_SIZE = 50; public void add. Element (char element); public void print. Reverse (); } User specific Implementation specific
Supporting Encapsulation package collections; public interface Char. History { public void add. Element (char element); public int size(); public char element. At (int index); }
Implementing the History package collections; public class AChar. History implements Char. History { public final int MAX_SIZE = 5; char[] contents = new char[MAX_SIZE]; int size = 0; public int size() { return size; } public char element. At (int index) { return contents[index]; } boolean is. Full() { return size == MAX_SIZE; } public void add. Element(char element) { if (is. Full()) { System. out. println("Adding item to a full history. Terminating program. "); System. exit(-1); } else { contents[size] = element; size++; } } }
Using the History package main; import enums. Char. Enumeration; import enums. An. Upper. Case. Enumeration; import collections. AChar. History; import collections. Char. History; public class AModular. Reverse. Upper. Case. Printer { static Char. History upper. Case. Letters = new AChar. History(); public static void main(String[] args) { if (args. length != 1) { System. out. println("Illegal number of arguments: " + args. length + ". Terminating program. "); System. exit(-1); } print. And. Store(args[0]); print. Reverse(); }
Using the History public static void print. And. Store (String s) { System. out. println("Upper Case Letters: "); print. And. Store (new An. Upper. Case. Enumeration(s)); } public static void print. And. Store (Char. Enumeration char. Enumeration) { while (char. Enumeration. has. More. Elements()) { char input. Char = char. Enumeration. next. Element(); System. out. print (input. Char); upper. Case. Letters. add. Element(input. Char); } System. out. println(); }
Forward and reverse printing (contd. ) public static void print. Reverse() { System. out. println("Upper Case Letters in Reverse: "); for (int index =upper. Case. Letters. size() - 1; index >= 0; index--) { System. out. print(upper. Case. Letters. element. At(index)); } } }
- Slides: 82