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)