50
CS 106 Introduction to Computer Science I 11 / 29 / 2006 Instructor: Michael Eckmann

CS 106 Introduction to Computer Science I 11 / 29 / 2006 Instructor: Michael Eckmann

Embed Size (px)

Citation preview

CS 106Introduction to Computer Science I

11 / 29 / 2006

Instructor: Michael Eckmann

Michael Eckmann - Skidmore College - CS 106 - Fall 2006

Today’s Topics• Comments and/or Questions?• Interfaces

– sorting using Comparables

• ArrayList class

• Wrapper classes for the primitive types

• Linked lists

Interfaces• Last class we wanted to write code that would sort an array of

Cards, so why do you think that sorting code we altered last time didn't take in an array of Cards?

• Instead it took in an array of Comparables.

Interfaces• Last class we wanted to write code that would sort an array of

Cards, so why do you think that sorting code we altered last time didn't take in an array of Cards?

• Instead it took in an array of Comparables.

• The code that we wrote that sorted Comparables will sort not only arrays of Cards, but arrays of any type whose class implements the Comparable interface. This is more useful in terms of code reuse --- it is more generic which is a very good thing.

Interfaces• In the next lab you'll create a class that implements

Comparable.

– A class to store contact information for someone. You'll store a person's first name, last name, and phone number.

– You'll create an array of Contacts and then sort that array.

– to sort it you can use the bubbleSort method which sorts an array of Comparables!

– How will it know how to sort Contacts?

Interfaces• So, the bubbleSort method that sorts Comparables now can

sort an array of

– Strings

– Cards

– Contacts

– references to any objects whose class implements the Comparable interface

Interfaces• Interfaces can have hierarchies just like classes have hierarchies

• That is, an interface can inherit from another interface.

• The child interface inherits everything from the parent interface (all the abstract methods and all the constants.)

• Any class that implements an interface

– must implement the interface's methods and all it's parents' methods

– gets access to all the constants in the child interface and the parents' interfaces

Interfaces• Example:

– All these interfaces are made up (they are NOT part of the Java API) – assume that they are interfaces we create ourselves.

– Let's say we have interfaces named Liquid, Drinkable, and TastyDrink.

– Let's assume that the TastyDrink interface inherits from Drinkable. And the Drinkable interface inherits from Liquid.

– A class, say Soda, implements the TastyDrink interface.

– Class Soda must provide implementations of all the abstract methods of TastyDrink, Drinkable and Liquid.

– Class Soda also has access to all the constants in the three interfaces.

Interfaces• A big difference between classes and interfaces is in the possible

hierarchies.

• Class hierarchies and interface hierarchies never overlap. They are kept seperate.

• Class hierarchies cannot have multiple inheritance, but interface hierarchies can. Example on board.

• Also, a class can extend only one other class, but can implement any number of interfaces.

• Eg. A class can implement both Comparable and Drinkable.

Interfaces• Interfaces can be used as a reference type. Anywhere you can use

other types (primitives or class names) you can use an interface name.

• Only objects of classes that implement the interface are allowed to be assigned to that reference variable.

• Example:

– We just saw that a method can have as a parameter a Comparable variable. (or in our case, an array of Comparables.)

– This means that the only objects that can be passed in to the method must be of a type (a class) that implements Comparable

• This is extremely useful as it allows use to write more generic code.

Designing classes• Before we discuss designing for polymorphism, I'd like to

discuss my opinions on what a good design for the last assignment is.

• A class to represent a Fraction. The best name for this class is Fraction. Why? because it represents one fraction.

• A class that contains static methods that determine primes, perfects, etc. I'll explain why I believe they should be static.

Designing classes• A class to represent a Fraction contains as instance data

– numerator

– denominator

• and methods to

– multiply

– divide

– add

– subtract

• Since these methods are non-static they'll need to be called by a Fraction object. But these methods all work on 2 Fractions so we'll take the second Fraction in as a parameter.

Designing classes• Fraction class shouldn't have any user input or output. It's

whole job should be to represent a fraction and provide behaviors of fractions (like arithmetic operations).

• We'll want to sometimes print a Fraction in a standard format so Fraction should provide a toString() method that returns a String like:

2 / 5

• This is better than a method in Fraction that actually does the printing to the console or a dialog box. Why?

Designing classes• This is better than a method in Fraction that actually does the

printing to the console or a dialog box. Why?

• Because the program that uses the Fraction class might want to write the fraction to a file or send it as an email message or print it to the console or print it in a dialog box or ...

• Providing a toString() method supplies the programmer with a way to get the Fraction as a String and then s/he can do whatever s/he wants to with that String.

• The Fraction class should be written so that it can be used by any program that needs Fractions regardless of what that program needs to do with them. It should be able to use the Fraction class as written, unaltered.

Designing classes• A class with static methods:

– isPrime• parameter: an int• return: boolean

– isPerfect• parameter: an int• return: boolean

Designing classes• Same class with these static methods:

– printPrimes• parameter: an int (representing the upper limit)• prints all the primes from 1 to upper limit• uses isPrime• returns nothing

– printPerfects• parameter: an int (representing the upper limit)• prints all the perfects from 1 to upper limit• uses isPerfect• returns nothing

• Why would I make these methods static?

Designing for polymorphism• Polymorphism allows a consistent approach to inconsistent but

related behaviors. What does that mean?

• First examine the problem to find opportunities that lend themselves to this before we write code.

• Let's look at some example situations and discuss them.

Designing for polymorphism• Different types of vehicles move in different ways

• All business transactions for a company must be logged

• All products produced by a company must meet certain quality standards

• A hotel needs to plan their remodeling efforts for every room

• A casino wants to analyze the profit margin for their games

• A dispatcher must schedule moving vans and personnel based on the job size

• A drawing program allows the user to draw various shapes

ArrayList• This is a good time to bring up a class in Java API named

ArrayList, because it works on general Objects.

• ArrayList is a class in the Java API

• It can store different types of data into an “array”

• An ArrayList can change size throughout the lifetime of the program

– whereas a regular array is a fixed size

• An ArrayList actually stores references to objects, not the objects themselves

• We cannot store values of primitive types directly -- we have to use the wrapper classes if we want to do that (we'll see what this means later).

ArrayList• Some ArrayList methods

– ArrayList() --- constructor

– boolean add(Object o) – add the object reference to the end of the list

– void add(int index, Object o) – add the object reference to the list at the index

– void clear() -- remove all elements from the list

– Object get(int index) – return the object reference at that index in the list

– int indexOf(Object o) – returns the index of the first occurrence of o

– boolean isEmpty() -- returns true if the list contains no elements, false otherwise

ArrayList• Some ArrayList methods

– Object remove(int index) – returns the object reference at that index in the list and removes it from the list

– int size() – returns the number of elements in the list

– boolean contains(Object o) -- returns true if the list contains o, false otherwise

– void ensureCapacity(int minCapacity) – tells Java to ensure that the list will be able to contain at least minCapacity references

– int lastIndexOf(Object o) – what do you think this does?

– boolean remove(Object o) -- removes a single instance of o from the list

– void removeRange(int fromIndex, int toIndex) --removes from the list all of the elements whose index is between fromIndex, inclusive and toIndex, exclusive.

ArrayList• Some ArrayList methods

– Object set(int index, Object o) -- replaces the element at the specified index in this list with o.

– What if this method wasn't in the class. How might you achieve that functionality?

ArrayList• Let's create an ArrayList of different types and add some elements to it

and remove some, etc...

• When we create one that allows different types, we have to cast any returned Objects from methods to be the type we want.

• Because Java implemented ArrayLists generically, and because of the way Java decided to have the class hierarchy such that all classes have Object as their superclass, this usefulness of ArrayLists is dramatically increased over a class that may have only allowed one type for its elements.

• So, that's a large benefit of good object oriented design --- generality --- so that you (or the Java implementers themselves) don't have to implement multiple classes to work on multiple types.

• If you create your class hierachy well, lots of stuff can be done generically (e.g. Have code that works on all Pets instead of just Dog or Cat objects for instance.)

ArrayList• If we stored several different types of data in a list, we may not know at

some point what type of object is actually stored in a particular index of the ArrayList.

• How do we find out what type a particular object actually is?

ArrayList• If we stored several different types of data in a list, we may not know at

some point what type of object is actually stored in a particular index of the ArrayList.

• How do we find out what type a particular object actually is?

• We can use the instanceof operator to check if some reference is an instance of some type.

e.g.

Object o = somearraylist.get(0);

if (o instanceof Contact)

{

//then cast o to be a Contact and use it

}

ArrayList• Let's look at how each method affected the list and what they returned.

– ArrayList() , boolean add(Object o) ,

– void add(int index, Object o) , void clear() , Object get(int index) ,

– int indexOf(Object o) , boolean isEmpty() ,

– Object remove(int index) , int size() , boolean contains(Object o) ,

– void ensureCapacity(int minCapacity) ,

– int lastIndexOf(Object o) , boolean remove(Object o) ,

– protected void removeRange(int fromIndex, int toIndex)

Polymorphism via Inheriance• An ArrayList uses polymorphism because it holds

references to objects of Object.

• An Object reference can be used to refer to any object (of any type)!!!

Wrapper classes• An ArrayList actually stores references to objects, not the objects

themselves so we cannot store values of primitive types directly -- we have to use the wrapper classes if we want to do that.

• The wrapper classes for the eight primitive types are:

– Integer for ints

– Float for floats

– Double for doubles

– Character for chars

– Short for shorts

– Long for longs

– Boolean for booleans

– Byte for bytes

Wrapper classes• Until now, we've only used static methods in these classes

• To use the static methods in a class you do not have to instantiate that class --- that is, you don't need an object of that class to call the static methods.

• For instance, we used parseInt in the Integer class whose functionality was just to take in a String and return the int that is stored in the String.

– int Integer.parseInt(String s)

• Similarly for

– double Double.parseDouble(String s)

• And for the other Wrapper classes as well.

Wrapper classes• But now, we need to instantiate these classes if we want a reference

to the data for some reason (e.g. for use in an ArrayList.)

• Let's add code like this to our program and see that ArrayLists can store these:

Integer i = new Integer(2);

stuff.add(i);

// necessary because a plain int is not a reference and

//therefore is not able to be in an ArrayList

• One thing though, the way the wrapper classes are written for all the primitive types, there's no way to actually change the value of variable once it's instantiated. There are no “set” methods.

Wrapper classes• Can anyone think of any use for maybe creating our own wrapper-

like classes?

• For example, when else might creating an instance of a class that stores one int vs. just storing the int as an int, be useful?

Wrapper classes• Can anyone think of any use for maybe creating our own wrapper-

like classes?

• For example, when else might creating an instance of a class that stores one int vs. just storing the int as an int, be useful?

• Do we recall how primitive types and class objects are passed (via parameters) into methods?

Wrapper classes• Can anyone think of any use for maybe creating our own wrapper-

like classes?

• For example, when else might creating an instance of a class that stores one int vs. just storing the int as an int, be useful?

• Do we recall how primitive types and class objects are passed (via parameters) into methods?

– Objects (including arrays) are passed by reference

– Primitive types are passed by value

–What are the implications of this?

Wrapper classes• Can anyone think of any use for maybe creating our own wrapper-

like classes?

• For example, when else might creating an instance of a class that stores one int vs. just storing the int as an int, be useful?

• Do we recall how primitive types and class objects are passed (via parameters) into methods?

– A reference to an object (including arrays) is passed in to method

–Whereas the value of a variable of a primitive type is passed in to a method

–What are the implications of this?

Wrapper classes• A reference to an object (including arrays) is passed in to method

• Whereas the value of a variable of a primitive type is passed in to a method

–What are the implications of this?

• Variables of primitive types cannot have their value changed because when a variable of a primitive type is passed in to a method, that method makes a copy of the variable for use within the method and the one passed in is unchanged.

• Why can an object's values change within a method?

Wrapper classes• A reference to an object (including arrays) is passed in to method

• Whereas the value of a variable of a primitive type is passed in to a method

– What are the implications of this?

• Variables of primitive types cannot have their value changed because when a variable of a primitive type is passed in to a method, that method makes a copy of the variable for use within the method and the one passed in is unchanged.

• Why can an object's values change within a method?

– Because the reference is passed into the method and the method uses the exact memory location of that reference to access/change that data.

– When the method call is made with an object reference parameter, a copy of the reference is made, not a copy of the data in that object.

Wrapper classes• So, if you want a value of a primitive type to possibly change within a

method, wrap it up in one of your own wrapper classes and make your method take in an object of the wrapper class type (not the primitive type.)

• e.g.public class IntWrapper

{

private int theint;

public IntWrapper(int theint)

{

this.theint = theint;

}

public void setInt(int theint)

{

this.theint = theint;

}

public int getInt()

{

return theint;

}

}

Wrapper classes• Then you could have a method that takes in an object reference of type

IntWrapper instead of a plain old int.

public void changeInt(IntWrapper i)

{

i.setInt(42);

}

• Call it like:

IntWrapper myint = new IntWrapper(3);

changeInt(myint);

• All that just so a method can change the value of an int!!!!

Wrapper classes• Could we use an object of type IntWrapper in an ArrayList?

Linked lists• A linked list is a data structure where every node contains data

and reference(s) to other node(s.)

Linked lists • In a singly linked list every node contains data and one

reference to another node.

– e.g.

class Node

{

public AnyType data; // can have more data than one

public Node next;

}

• A Linked List is maintained by keeping a reference to the head of the list.

• From the head, we are able to get at all the other nodes in the list by following the next reference.

Linked lists class Node

{

public AnyType data; // can have more data than one

public Node next;

// when constructing a new node, we set its data and

// set the next reference to null

public Node(AnyType d)

{

data = d;

next = null;

}

}

Linked lists Node n = new Node(somedata);

Node head;

head = n; // sets n to be the head of the linked list

Node newnode = new Node(somedata2);

// to add a newnode to the beginning of the list:

newnode.next = head;

head = newnode;

Linked lists Node newnode = new Node(somedata2);

// to add a newnode to the end of the list:

Node currnode;

currnode = head;

while (currnode != null)

{

savenode = currnode;

currnode = currnode.next;

}

savenode.next = newnode;

Linked lists • Let's figure out how to

– Insert after a particular node

// insert newnode after findnode

currnode = head;

while (!((currnode.card).equals(findnode.card)))

{

currnode = currnode.next;

}

newnode.next = currnode.next;

currnode.next = newnode;

Linked lists• Let's figure out how to

– Delete a node

// delete findnode

Node prevnode;

Node currnode = head;

while (!((currnode.card).equals(findnode.card)))

{

prevnode = currnode;

currnode = currnode.next;

}

prevnode.next = currnode.next;

currnode = null;

Linked lists• Let's figure out how to

– Insert after a particular node

–Delete a particular node

• Other options

– Storing link to last node

–Doubly linked lists (and their operations.)

Linked lists • A doubly linked list is a data structure where every node

contains

– data

– a reference to previous node

– a reference to next node

• What do you think the value of the next node is for the last element of a linked list?

• What do you think the value of the previous node is for the first element of a linked list?

Linked lists• Let's implement our deck of cards as a linked list of card nodes

instead of as an array of cards.

Linked lists• Compare a linked list's behaviors to that of arrays and

ArrayLists.

–Which are dynamic in length?

–How about ease of operations in terms of:

• speed of execution and • programmer ease

–Consider these operations:• Add• Insert• Delete