CS62 - Spring 2020 - Class 3
Example code in this lecture
Initialization
CardDealer
Inheritance
Lecture notes
Admin
- lab tomorrow. start in Edmunds 229
- CS lab computers still not working
initializing variables
- When we declare a new variable, Java creates a new space in memory for the value
- if it's a primitive type, the value will go directly there
- if it's anything else, it will be a reference to an object
- We often will declare the variable and assign to it immediately:
int x = 2;
Card c = new Card(1, "hearts");
- However, we can also decouple these steps:
int x;
x = 2;
Card c;
c = new Card(1, "hearts");
- What would happen if we looked at/printed out the value of a variable *before* assigning to it? - In some languages, this isn't well defined!
- In Java, when you create a variable without assigning to it, it gets a default value
- For the primitive types, it's something reasonable (often 0)
- For everything else, we get "null"
- null is Javas way of indicating that this variable is not associated with a value.
look at Initialization.java in
Initialization code
- What would happen if we run test1()?
- Where is the constructor?!?
- If you don't specify a constructor, Java will automatically generate a zero parameter constructor for you
- We'll see:
2
4 of hearts
- What would happen if we run test2()?
- We haven't set the values, so we'll get the default values
0
null
- What would happen if we run test3()?
- try to call a method on an object that doesn't exist!
java.lang.NullPointerException
- You will get null pointer exceptions
- it just happens if you program long enough in Java
- The cause is that you tried to access some value as if it were an object, but it was actually null
What does the constructor do in FixedCardDealer in
CardDealer code
- What does the constructor do?
- creates a new array for number of decks * 13 * 4 entries
- adds each card for each deck to the array
- outer loop is over the number of decks
- second loop is over suits
- third loop is over numbers
initializing arrays
- often, we'll initialize an array and then fill it in, e.g.,
int[] x = new int[10];
x[0] = 2;
...
- sometimes (e.g., with constants), we'll want to initialize the array with values. To do this, use curly braces
int[] x = {1, 2, 3, 4, 5};
Look at the FixedCardDealer in
CardDealer code
- What does the shuffle method do?
- for each card, pick another random entry and swap the entries
- Where does Random come from?
- it's a package!
A package is a collection of classes
- usually they're related
- Any class inside a particular package may use any other class in the package without doing anything special
- If you want to use a class that is not inside your package, you need to import it
- To import a class:
import <package_name>.<class_name>
- sometimes, there are nested packages, e.g.
import <outer_package>.<inner_package>.<class_name>
- For example:
import java.util.Random
- imports the Random class from the java.util package
import java.util.Scanner
- imports the Scanner class from the java.util package
- To write your own package:
- Packages are indicated in two ways (both are required):
1) All classes inside a packages should be in a directory with the packages name
2) All classes inside a package should start with package <package_name>;
Look at the FixedCardDealer in
CardDealer code
- What does the printDeck method do?
- it's static, so it doesn't have access to the instance variables
- creates a new card dealer and then prints out the entire deck
- utilizes next and getNext
- both use position to keep track of where we are
- using this pair of methods is a common way to iterate through data. we'll see it a lot!
What if we wanted to add an addDeck method?
- We could do it, but it would be a bit painful
- have to create a new array that's one deck larger
- copy the existing cards over
- then add another deck
ArrayLists
- Arrays are of fixed length and are built into the language
- ArrayLists are built on top of arrays (underneath the covers, they are implemented using arrays), but they allow much more functionality than arrays
- they are much more similar to lists in python
- ArrayLists are a class, so to use them you create them by calling the constructor and then interact with them via methods
- Constructing a new ArrayList
ArrayList<type_of_items> name = new ArrayList<type_of_items>();
e.g.,
ArrayList<Card> cards = new ArrayList<Card>();
- This is calling the constructor with a bit of information about what type of thing we're going to be storing in the ArrayList
- ArrayLists have many methods, the most common we'll use now are:
- size()
- how many things are in the ArrayList
- get(index)
- get the value at index (will be of whatever type the ArrayList was initialized as)
- set(index, value)
- set entry at index to value. index must be between 0 and size()-1 and the value must be of the type that was initialized.
- add(value)
- add the value to the end of the ArrayList and increase the size by 1
- this is something we couldn't do easily with arrays!
Look at CardDealerArrayList class in
CardDealer code
- Almost identical to FixedCardDealer!
- Constructor is simpler since we don't have to precalculate the size or keep track of the current index
- shuffle uses get/set
- Can now support the addDeck functionality without too much difficulty
Look at CardDealer class in
CardDealer code
- any time you have repeated code you should consider making a helper method with the code and then calling it instead
- the addDeckWithoutShuffle method adds a single deck and we can add call it in both addDeck and the constructor
Run main method in ShapeMaker class from
Inheritance code
- takes as input a number
- can enter the name of the shape
- squares and rectangles are well defined
- other shapes can be defined, but area doesn't work as expected
- somewhere in the code, I'd like to be able to store multiple shapes with names, etc., and then be able to run through them and calculate their area
- a very natural way of doing this is to create one class per shape
inheritance
- we can build a new class that is an extension of another class
- the original class is said to be the superclass (or parent class) and the new class the subclass (or child class)
- to do this, in the class header, you use the keyword "extends", e.g.
public class B extends A{
...
}
- the subclass:
- inherits all public methods from the superclass
- e.g. given an object of type B, we can call any method that A had on B
- can access any instance variables that are declared public *or* protected
- can call any methods that are declared as public *or* protected
- additions in the subclass
- you can then add any additional instance variables and methods in the subclass
- these will be available normally in the subclass, but NOT in the superclass
- if you define a method with the same "signature" as in the superclass, it will override it
protected
- labeling a variable as protected allows the child class to access that variable, but no other classes
- labeling a method as protected allows the child class to access those methods, but no other classes
the Java class hierarchy
- *everything* in Java is a subclass of some class (except for 1 class in Java)
- you can only inherit from one class
- if you don't inherit from a class, by default, you inherit from the class Object
- You can see the object hierarchy at:
http://docs.oracle.com/javase/7/docs/api/overview-tree.html
Look at
Inheritance code
- We have a class called A that has a private and protected instance variable
- Two public methods
- B is a class that inherits from A
- we indicate this with the keyword "extends"
- B has all of the instance variables of A
- however, it can only access those that are protected or public
- in the resetInt method, we can access number
- if we tried to access the text variable, we would get an error
super
- if the superclass has a constructor that has parameters, then it needs information to be constructed
- when a subclass extends a superclass, it, in essence, has a version of the superclass nested inside of it
- because of this, when constructing the subclass, the superclass also need to be constructed
- to call the superclass's construct, you use the keyword "super"
- it has to be the *first* thing that happens in the constructor of the sublcass
types
- an A object is of type A
- a B object is of type B
- a B object is also of type A!
- For example, the following are all legal:
A temp = new A(10, "blah");
B temp = new B(10, "blah");
A temp = new B(10, "blah");
- but the following is not:
B temp = new A(10, "blah");
look at the test method in the B class in
Inheritance code
- What will be printed out when we run it?
10
0
10
- notice that the B class inherits all of the public methods from the A class
- specifically, we call the getNumber method and it gets the method description from the A class
- also note that even though we do not have any instance variables declared, we inherit all the instance variables from A (number and text)
- If we tried to call the resetInt method on an A object, it won't work!
look at test2
- What ill be printed out?
test
- We've declared a variable of type A, why can we assign a B object to it?
- All B object have the A methods!
- Why can't we can't the resetInt method?
- Even though it's a B object (and we know it), the Java compiler can't guarantee it:
For example:
A a;
if( rand.randInt(2) == 1 ){
a = new A(10, "test");
}else{
a = new B(10, "test");
}
// we have no idea if a references an A or a B!
look at test3
- What will be printed out?
A1: I'm an A
B1: I'm a B
A2: I'm a B
- Since A2 references an object of type B, then B's toString method gets called!
- When the methods are called, they are based on the object
look at the classes in the
Inheritance code
- The Shapes class defines basic behavior
- The Square and Rectangle classes extend the Shape class
- they both override the getArea method
- they both add methods particular to the class
look at ShapeMaker class in
Inheritance code
- What does the getShapes method do?
- prompts the user for a number
- then prompts them for that number of shapes
- if the user enters a rectangle or square it creates one
- otherwise creates a generic shape
- Where does it store these shapes?
- in an ArrayList of Shapes
- Why does that work?
- Rectangles and Squares are both shapes!
- What does the printShapes method do?
- goes through the Shape ArrayList and prints each shape out (i.e. calls the toString method)