70
Session 5 More on Java Strings and Files & Intro. to Inheritance

Session 5 More on Java Strings and Files & Intro. to Inheritance

Embed Size (px)

Citation preview

Page 1: Session 5 More on Java Strings and Files & Intro. to Inheritance

Session 5

More on Java Strings and Files& Intro. to Inheritance

Page 2: Session 5 More on Java Strings and Files & Intro. to Inheritance

Java File I/O

• Allows us to write and read “permanent” information to and from disk

• How would file I/O help improve the capabilities of the MemoPadApp?

Page 3: Session 5 More on Java Strings and Files & Intro. to Inheritance

Java File I/O Example: Echo.java• echoes all the words in one file to an output

file, one per line.

$ java Echo hamlet.txt hamlet.out

$ less hamlet.out

1604

the

tragedy

of

hamlet

prince

of

denmark

by

william

shakespeare ...

Page 4: Session 5 More on Java Strings and Files & Intro. to Inheritance

Study Echo.java’s File I/O

• have constructors that allow convenient and flexible processing

• send input message: readLine()

• send output messages: print() and println()

• use a stereotypical loop to process a file of lines

• use of the stereotypical StringTokenizer loop as inner loop

Page 5: Session 5 More on Java Strings and Files & Intro. to Inheritance

import java.io.*;import java.util.StringTokenizer;

public class Echo { public static void main( String[] args ) throws IOException { String delimiters = " .?!()[]{}|?/&\\,;:-\'\"\t\n\r";

BufferedReader inputFile = new BufferedReader(new FileReader(args[0]) ); PrintWriter outputFile = new PrintWriter( new FileWriter( args[1] ) );

String buffer = null;

while( true ) { buffer = inputFile.readLine();

if ( buffer == null ) break;

buffer = buffer.toLowerCase(); StringTokenizer tokens = new StringTokenizer( buffer, delimiters );

while( tokens.hasMoreElements() ) { String word = tokens.nextToken(); outputFile.println( word ); } // end while } // end while(true)... } // end main} // end class Echo

Page 6: Session 5 More on Java Strings and Files & Intro. to Inheritance

wc - UNIX/Linux utility

• wc prints the number of lines, words, and characters in a file to standard output.

• For example:

$ wc hamlet.txt

4792 31957 196505 hamlet.txt

Page 7: Session 5 More on Java Strings and Files & Intro. to Inheritance

Exercise

• Using Echo.java as your starting point, create a WordCount.java program that does the same thing as wc, i.e., prints the number of lines, words, and characters in a file to standard output. For example:

$ java WordCount hamlet.txt lines = 4792 words = 32889 chars = 130156

Page 8: Session 5 More on Java Strings and Files & Intro. to Inheritance

import java.io.*;import java.util.StringTokenizer;

public class WordCount { public static void main( String[] args ) throws IOException { String delimiters = " .?!()[]{}|?/&\\,;:-\'\"\t\n\r";

BufferedReader inputFile = new BufferedReader( new FileReader( args[0] ) );

String buffer = null; int chars = 0; int words = 0; int lines = 0;

while( true ) { buffer = inputFile.readLine();

if ( buffer == null ) break;

lines++;

buffer = buffer.toLowerCase(); StringTokenizer tokens = new StringTokenizer( buffer, delimiters );

while( tokens.hasMoreElements() ) { String word = tokens.nextToken(); words++; chars += word.length(); } // end while } // end while( true )...

System.out.println( "" + lines + " " + words + " " + chars ); } // end main} // end class WordCount

Page 9: Session 5 More on Java Strings and Files & Intro. to Inheritance

Why the difference in the number of words and number of characters?

$ wc hamlet.txt

4792 31957 196505 hamlet.txt

$ java WordCount hamlet.txt

lines=4792 words=32889 chars=130156

Page 10: Session 5 More on Java Strings and Files & Intro. to Inheritance

Java File I/O Example: Echo.java• echoes all the words in one file to an output

file, one per line.

$ java Echo hamlet.txt hamlet.out

$ less hamlet.out

1604

the

tragedy

of

hamlet

prince

of

denmark

by

william

shakespeare ...

Page 11: Session 5 More on Java Strings and Files & Intro. to Inheritance

import java.io.*;import java.util.StringTokenizer;

public class Echo { public static void main( String[] args ) throws IOException { String delimiters = " .?!()[]{}|?/&\\,;:-\'\"\t\n\r";

BufferedReader inputFile = new BufferedReader(new FileReader(args[0]) ); PrintWriter outputFile = new PrintWriter( new FileWriter( args[1] ) );

String buffer = null;

while( true ) { buffer = inputFile.readLine();

if ( buffer == null ) break;

buffer = buffer.toLowerCase(); StringTokenizer tokens = new StringTokenizer( buffer, delimiters );

while( tokens.hasMoreElements() ) { String word = tokens.nextToken(); outputFile.println( word ); } // end while } // end while(true)... } // end main} // end class Echo

Page 12: Session 5 More on Java Strings and Files & Intro. to Inheritance

Working with Standard Input and Output as Files

• Sometimes, we'd like to give the user an option of providing a file name or using standard I/O.

• We can call sort with its own file argument, or we can pipe the standard output of one program (cat hamlet.out) as the standard input to sort.

• How can we make our Java programs do the same thing?

Page 13: Session 5 More on Java Strings and Files & Intro. to Inheritance

Streams vs. Readers and Writers

• a stream is a device for transmitting or receiving a sequence of byte (8-bit) values– emphasis on reading/writing -- not on data itself– network and file systems are based on byte unit

• Readers and Writers use 16-bit Unicode – useful for I/O of textual values as opposed to

binary data such as images, colors, etc.– for example, BufferedRead has readLine method

Page 14: Session 5 More on Java Strings and Files & Intro. to Inheritance

Working with Standard Input and Output as Files

• Standard input is an instance of the InputStream class and does not respond to readLine(), which is how we would like to grab lines of text as Strings.

• Standard output does respond to println() messages, but it is a PrintStream, which cannot be stored in a PrintWriter variable.

Page 15: Session 5 More on Java Strings and Files & Intro. to Inheritance

What can we do?

• We could write duplicate code for the four different cases. (file-file, file-stdout, stdin-file, stdin-stdout)

• Every case would look the same except for one or two lines.

• That doesn't seem to be the correct solution.

• Maybe we can find a way to have them talk to objects that talk to standard input and output...

Page 16: Session 5 More on Java Strings and Files & Intro. to Inheritance

A Solution• Let's take advantage of an object-oriented idea: We ought

to be able to substitute an object with a common interface, even if somewhat different behavior, in place of one another, and let the new object fulfill the responsibilities of the replaced one.

• While BufferedReaders and PrintWriters don't know how to talk to standard input and output, respectively, we can use a translator to serve as a go-between.

• Java give us the classes we need: InputStreamReader and OutputStreamWriter.

Page 17: Session 5 More on Java Strings and Files & Intro. to Inheritance

import java.io.*;import java.util.StringTokenizer;

public class EchoStandard { public static void main( String[] args ) throws IOException { String delimiters = " .?!()[]{}|?/&\\,;:-\'\"\t\n\r";

BufferedReader inputFile = new BufferedReader( new InputStreamReader( System.in ) ); PrintWriter outputFile = new PrintWriter( new OutputStreamWriter( System.out ) );

String buffer = null;

while( true ) { buffer = inputFile.readLine();

if ( buffer == null ) break;

buffer = buffer.toLowerCase(); StringTokenizer tokens = new StringTokenizer(buffer,delimiters);

while( tokens.hasMoreElements() ) { String word = tokens.nextToken(); outputFile.println( word ); } // end while } // end while( true )... } // end main} // end class EchoStandard

Page 18: Session 5 More on Java Strings and Files & Intro. to Inheritance

Echo

BufferedReader inputFile = new BufferedReader(

new FileReader( args[0]) );

PrintWriter outputFile = new PrintWriter(

new FileWriter( args[1]) );

vs. EchoStandard

BufferedReader inputFile = new BufferedReader(

new InputStreamReader( System.in ) );

PrintWriter outputFile = new PrintWriter(

new OutputStreamWriter( System.out ) );

Page 19: Session 5 More on Java Strings and Files & Intro. to Inheritance

Exercise• Turn Echo.java into EchoV2.java, which behaves just like Echo,

except that it takes two optional command-line arguments: the names of the input file and output file, respectively.

• If the user omits the second argument, the program writes to standard output.

• If the user omits both arguments, the program reads from standard output and writes to standard output. For example:

$ java EchoV2 hamlet.txt hamlet.out

$ less hamlet.out

1604

the

tragedy

of

...

Page 20: Session 5 More on Java Strings and Files & Intro. to Inheritance

Exercise - More Examples$ java EchoV2 EchoV2.java

...

$ java EchoV2 hamlet.txt | less (interesting that the pipe “|” is not args[1])

1604

the

tragedy

of

...

$ java EchoV2

...

$ cat hamlet.txt | java EchoV2 | less

1604

the

tragedy

of

...

Page 21: Session 5 More on Java Strings and Files & Intro. to Inheritance

Introduction to Inheritance

Page 22: Session 5 More on Java Strings and Files & Intro. to Inheritance

Accumulator Example• a simple calculator app• classes needed:

– AdderApp - contains main– AddingFrame - GUI

– CloseableFrame - allows X button

– Accumulator - internal representation and implementation of the accumulator

Page 23: Session 5 More on Java Strings and Files & Intro. to Inheritance

AdderApp

• contains the main() method that serves as the "Big Bang" for this part of the world

public class AdderApp {

public static void main( String[] args ) {

AddingFrame f = new AddingFrame();

f.show();

} // end main

} // end class AdderApp

Page 24: Session 5 More on Java Strings and Files & Intro. to Inheritance

AddingFrame

• Provides the graphical interaction between the user and the actual calculator methods

• AddingFrame extends CloseableFrame extends JFrame.

• AddingFrame depends on the Accumulator class do the mathematics for the program.

Page 25: Session 5 More on Java Strings and Files & Intro. to Inheritance

Accumulator Class

• Recall from CS I that a class contains three things. – Data / Instance Variables– Method(s)– Constructor(s)

Page 26: Session 5 More on Java Strings and Files & Intro. to Inheritance

Accumulator Class• What Data / Instance Variables are needed?

Page 27: Session 5 More on Java Strings and Files & Intro. to Inheritance

Accumulator Class• Data / Instance Variables needed:

– currentSum – the current value “accumulated” by the accumulator.

– currentNumber – the number that has been entered by the user. The value that will be added or subtracted.

– displayValue – the value visible on the graphical calculator. (Needed because sometimes we display the number the user is entering (currentNumber) and sometimes it is the current accumulated value (currentSum), so we will maintain a new value which holds whatever is on display.)

Page 28: Session 5 More on Java Strings and Files & Intro. to Inheritance

Accumulator Class

• What methods would the accumulator class need (hint, there are five of them)?

Page 29: Session 5 More on Java Strings and Files & Intro. to Inheritance

Accumulator Class

• Needed methods:– plus – adds the last number entered to the currentSum.– minus – subtracts the last number entered from the

currentSum.– clear – sets everything back to zero– addDigit – adjusts the currentNumber upon input of an

additional integer– getDisplay – returns the current displayValue. (This is

necessary because our graphical class will want to know what value to display any time some action occurs.)

Page 30: Session 5 More on Java Strings and Files & Intro. to Inheritance

Accumulator Class

• What would the constructor do?

Page 31: Session 5 More on Java Strings and Files & Intro. to Inheritance

AccumulatorV1public class AccumulatorV1 {

private int currentSum;

private int currentNumber;

private int displayNumber;

public Accumulator() {

currentSum=0;

currentNumber=0;

displayNumber=0;

}

public void clear() {

currentSum=0;

currentNumber=0;

displayNumber=0;

}

public void addDigit( int digit ) {

currentNumber=currentNumber*10+digit;

displayNumber=currentNumber;

}

public void plus() {

currentSum+=currentNumber;

currentNumber=0;

displayNumber=currentSum;

}

public void minus() {

currentSum-=currentNumber;

currentNumber=0;

displayNumber=currentSum;

}

public int getDisplay() {

return displayNumber;

}

} // end class AccumulatorV1

Page 32: Session 5 More on Java Strings and Files & Intro. to Inheritance

Refactoring Accumulator

• What is refactoring? – Changing a program in a way that does not

change its functionality.

• Why do it? – To improve the structure of your code based on

what you have learned since writing it.

• What common code can we refactor?

Page 33: Session 5 More on Java Strings and Files & Intro. to Inheritance

Refactoring Accumulator

• Using the clear() method in the constructor

• Refactoring the plus() and minus() methods to call a private helper method.

Page 34: Session 5 More on Java Strings and Files & Intro. to Inheritance

Refactoring Accumulator public void plus() {

currentSum+=currentNumber;

prepareForNextNumber();

}

public void minus() {

currentSum-=currentNumber;

prepareForNextNumber();

}

private void prepareForNextNumber() {

currentNumber=0;

displayNumber=currentSum;

}

public int getDisplay() {

return displayNumber;

}

} // end class AccumulatorV2

public class AccumulatorV2 { private int currentSum; private int currentNumber; private int displayNumber; public Accumulator() { clear(); } public void clear() { currentSum=0; currentNumber=0; displayNumber=0; } public void addDigit( int digit ) { currentNumber=currentNumber*10+digit; displayNumber=currentNumber; }

Page 35: Session 5 More on Java Strings and Files & Intro. to Inheritance

Reinforcing the refactoring

• There is an old programmers adage that states

        "There are only two numbers: 1 and many"

• Once you start to repeat code, it is time to start to think about refactoring and adding in a helper method.

Page 36: Session 5 More on Java Strings and Files & Intro. to Inheritance

Alternative structure of the program

• The complete “calculator” consists of four classes.– AdderApp– AddingFrame– CloseableFrame– Accumulator

Page 37: Session 5 More on Java Strings and Files & Intro. to Inheritance

Alternative structure of the program• We can think of the relationships between

these four classes as being “narrow and deep”– AdderApp creates an instance of AddingFrame

which creates an instance of Accumulator.– This is a good example of data hiding since

AdderApp doesn’t know/care that there is an instance of the Accumulator class.

public class AdderApp { public static void main( String[] args ) { AddingFrame f = new AddingFrame(); f.show(); } // end main} // end class AdderApp

public class AddingFrame extends CloseableFrame { private Accumulator myAccumulator; ... public AddingFrame( ) {

// create frame and accumulatormyAccumulator = new Accumulator();

...

Page 38: Session 5 More on Java Strings and Files & Intro. to Inheritance

Alternative structure of the program• But another way to structure this program would be to

create a relationship which is “wide and shallow”– AdderApp creates an an instance of Accumulator which it

passes to an instance of AddingFrame. public class AdderApp { public static void main( String[] args ) {

Accumulator a = new Accumulator();

AddingFrame f = new AddingFrame(a);

f.show();

} // end main

} // end class AdderApp

– This is a good example of composition. • We emphasize that AddingFrame is composed of an Accumulator

– This is a good example of writing code that is modular.• Now that we know the composition relation, we can compose

solutions using variations of Accumulator.

Page 39: Session 5 More on Java Strings and Files & Intro. to Inheritance

CountedAccumulator Extension

• Suppose we need a new kind of object, an Accumulator that counts how many operations it executes. Let’s call this class CountedAccumulator.

• It responds to all the same messages as a regular Accumulator and also responds to an operationsExecuted() message, by returning its count.

• What changes would you need to make to Accumulator?

Page 40: Session 5 More on Java Strings and Files & Intro. to Inheritance

Adding Behavior to a Class• Any time that we need to add behavior to a

class we have at least three options:– Add code to the class itself, keeping the

original class. – Copy all the old code into a new class and add

code to this new class.– Create a subclass that extends the original

class' behavior.

Page 41: Session 5 More on Java Strings and Files & Intro. to Inheritance

Pros and Cons

“Add code to the class itself, keeping the original class. “– Pros: Quick. Convenient. Simple.– Cons: May change the behavior of the class.

Thus, it isn’t always an option.

Page 42: Session 5 More on Java Strings and Files & Intro. to Inheritance

Pros and Cons

“Add code to the class itself, keeping the original class. “– Pros: Quick. Convenient. Simple.– Cons: May change the behavior of the class.

Thus, it isn’t always an option.

Page 43: Session 5 More on Java Strings and Files & Intro. to Inheritance

Pros and Cons

“Add code to the class itself, keeping the original class. “– Pros: Quick. Convenient. Simple.– Cons: May change the behavior of the class.

Thus, it isn’t always an option.

Page 44: Session 5 More on Java Strings and Files & Intro. to Inheritance

Pros and Cons

“Copy all the old code into a new class and add code to this new class. “– Pros: Quick. Convenient. Simple.– Cons: Duplicated code. Error trap! Error trap!

Page 45: Session 5 More on Java Strings and Files & Intro. to Inheritance

Pros and Cons

“Copy all the old code into a new class and add code to this new class. “– Pros: Quick. Convenient. Simple.– Cons: Duplicated code. Error trap! Error trap!

Page 46: Session 5 More on Java Strings and Files & Intro. to Inheritance

Pros and Cons

“Copy all the old code into a new class and add code to this new class. “– Pros: Quick. Convenient. Simple.– Cons: Duplicated code. Error trap! Error trap!

Page 47: Session 5 More on Java Strings and Files & Intro. to Inheritance

Pros and Cons

“Create a subclass that extends the original class' behavior.“– Pros: Doesn’t break existing code. Virtually

eliminates duplicate code. Provides the most flexibility.

– Cons: Slightly more time consuming.

Page 48: Session 5 More on Java Strings and Files & Intro. to Inheritance

Pros and Cons

“Create a subclass that extends the original class' behavior.“– Pros: Doesn’t break existing code. Virtually

eliminates duplicate code. Provides the most flexibility.

– Cons: Slightly more time consuming.

Page 49: Session 5 More on Java Strings and Files & Intro. to Inheritance

Pros and Cons

“Create a subclass that extends the original class' behavior.“– Pros: Doesn’t break existing code. Virtually

eliminates duplicate code. Provides the most flexibility.

– Cons: Slightly more time consuming.

Page 50: Session 5 More on Java Strings and Files & Intro. to Inheritance

Developing an Extended Class

• There are typically four steps in developing an extended class.– declare the class– declare the new data – create the constructors  – adjust the methods

Page 51: Session 5 More on Java Strings and Files & Intro. to Inheritance

Developing an Extended Class

• declare the class

public class CountedAccumulator extends Accumulator {

Page 52: Session 5 More on Java Strings and Files & Intro. to Inheritance

Developing an Extended Class

• declare the new data

private int numberOfOperations;

Page 53: Session 5 More on Java Strings and Files & Intro. to Inheritance

Developing an Extended Class

• create the constructor        

public CountedAccumulator () {

super();

numberOfOperations=0;

}

Page 54: Session 5 More on Java Strings and Files & Intro. to Inheritance

Developing an Extended Class

•   Leave inherited methods alone – clear() and prepareForNextNumber() are both

inherited from Accumulator and there is no need to change them.

Page 55: Session 5 More on Java Strings and Files & Intro. to Inheritance

Developing an Extended Class

• Modify/Override inherited methods– plus() and minus() are inherited, but they don't do what

we want them to.  – We can make them do more without completely

replacing the code however.

public void plus() {super.plus();numberOfOperations++;

}

Page 56: Session 5 More on Java Strings and Files & Intro. to Inheritance

Developing an Extended Class

• Add completely new methods – We need an accessor method for numberOfOperations

public void operationsExecuted() {

        return numberOfOperations;

}

Page 57: Session 5 More on Java Strings and Files & Intro. to Inheritance

CountedAccumulator Solutionpublic class CountedAccumulator extends Accumulator {

private int numberOfOperations;

public CountedAccumulator() {

super(); // calls the superclass’ constructor

numberOfOperations=0;

}

public void plus() {

super.plus();

numberOfOperations++;

}

public void minus() {

super.minus();

numberOfOperations++;

}

public int getOperations() {

return numberOfOperations;

}

} // end class CountedAccumulator

Page 58: Session 5 More on Java Strings and Files & Intro. to Inheritance

CountedAccumulator Solution• Now, before we can really work with this

we need to modify other files in our application. 

• We need to set up the AddingFrame so that it works with a CountedAccumulator rather than a regular Accumulator.  We do this in the AdderApp class for simplicity.

Accumulator a = new CountedAccumulator();

AddingFrame f = new AddingFrame(a);

Page 59: Session 5 More on Java Strings and Files & Intro. to Inheritance

A solution• Why do we do this in the AdderApp rather than

leave it alone and modify the AddingFrame?  – Because in the end this makes our AddingFrame

slightly more versatile. 

– Think about it...AddingFrame works with an Accumulator (or CountedAccumulator).  If one is provided, it uses it.  If one is not provided, it creates it. 

– THAT, is more versatile than telling an AddingFrame to now always create a CountedAccumulator.

Page 60: Session 5 More on Java Strings and Files & Intro. to Inheritance

A solution

• Now we can run this... – Notice that we have basically returned to

having a Accumulator.  Why? – Notice that even though I have private data and

methods in Accumulator, I didn't have to change this here.  Why?

Page 61: Session 5 More on Java Strings and Files & Intro. to Inheritance

A solution that USES the counting functionality

• If we want to actually use the functionality of this new class, then something needs to call the new method in CountedAccumulator.

• Without discussing the details of exception handling, we could do this by writing:

try {Thread.sleep(10000);

} catch(Exception e) {}System.out.println("Performed“

+a.getOperations()+"operations");

Page 62: Session 5 More on Java Strings and Files & Intro. to Inheritance

Another Exercise

Create a class named EvenOddAccumulator that subclasses Accumulator to implement this behavior.

EvenOddAccumulators respond to all the same messages as regular Accumulators. But, in response to plus() and minus() messages, an EvenOddAccumulator both computes the new sum and writes a congratulatory message if the sum is even.

Page 63: Session 5 More on Java Strings and Files & Intro. to Inheritance

Toward a Solution

Here is the critical new piece of the EvenOddAccumulator class:

if ( currentSum % 2 == 0 ) {System.out.println( "Hurray! You made an even number." );

}

The big question is, what else is a part of the class?

Page 64: Session 5 More on Java Strings and Files & Intro. to Inheritance

Toward a Solution

• Let’s look at one version of this…

Page 65: Session 5 More on Java Strings and Files & Intro. to Inheritance

A Problem Accessing Inherited Data$ javac EvenOddAccumulator.javaEvenOddAccumulator.java:17: currentSumhas private access in Accumulatorif ( currentSum % 2 == 0 )^EvenOddAccumulator.java:24: currentSumhas private access in Accumulatorif ( currentSum % 2 == 0 )^2 errors

Oops!currentSum is declared as a private instance variable in class Accumulator. private means private: no code outside the Accumulator class can access

that variable.

Page 66: Session 5 More on Java Strings and Files & Intro. to Inheritance

A Possible Solution for Accessing Inherited Data

• Change currentSum to be public or protected.

public class Accumulator {

protected int currentSum;

...

}

Page 67: Session 5 More on Java Strings and Files & Intro. to Inheritance

A Better Solutionfor Accessing Inherited Data

(2) Add a protected “accessor” method to theAccumulator class. Use that method to access thecurrentSum instance variable in the subclass.

public class Accumulator {...protected int currentSum() {

return currentSum;}

}

Then use currentSum() in EvenOddAccumulator.

Page 68: Session 5 More on Java Strings and Files & Intro. to Inheritance

Programming with Inheritance

Inheritance is an object-oriented programming construct that enables us to add behavior to an existing system without modifying the existing classes.

Page 69: Session 5 More on Java Strings and Files & Intro. to Inheritance

Programming with InheritanceOur new EvenOddAccumulator class adds behavior to a program

that uses Accumulators without modifying:• the behavior of the existing Accumulator class or• the existing AddingFrame class!

That means...• No chance of introducing an unnecessary, unexpected errors

into the working Accumulator class.• No need to modify programs that use instances of

Accumulator but which don’t need instances of EvenOddAccumulator.

• The ability to use EvenOddAccumulators in programs that expect to use Accumulators.

Page 70: Session 5 More on Java Strings and Files & Intro. to Inheritance

Programming with Inheritance

We could have achieved some of these results without using inheritance by creating a new class named EvenOddAccumulator that simply duplicated the behavior of existing Accumulator class.

Using inheritance means that...• No need to reimplement existing methods.• No need to duplicate code.

One of the most important features of object-oriented programming is that it encourages us to create new classes that reuse existing code as much as possible. Without inheritance, you have only one tool for doing that, composition. With inheritance, you have two tools.