CS51 - Spring 2010 - Lecture 14

  • http://www.xkcd.com/810/

  • summing up the numbers from 1 to some input, n
       private int sum(int n){
          ...
       }

       - iterative version:
          private int sum(int n){
             int totalSum = 0;

             while( n > 0 ){
                totalSum += n;
                n--;
             }

             return totalSum;
          }

       - procedural recursion
          - the recursion we've seen so far is called structural recursion, where we define an object with respect to itself
          - in procedural recursion, we define a method with respect to a recursive method call

       - recursive version:
          - how can we define this recursively (in words)?
             - the sum of the numbers from 1...n is n plus the sum of the numbers from 1...n-1
          - what is our recursive case?
             - sum(n) = n + sum(n-1)
          - what is our base case? When do we stop?
             - if n is equal to 1, then we know that the sum is 1
          - write the method:

          private int sum(int n){
             if( n == 1 ){
                return 1;
             } else {
                return n + sum(n-1);
             }
          }
       - why does this work?
          - first, we call it with n
          - we return n plus whatever is returned by sum(n-1)
          - which returns n-1 plus whatever is returned by sum(n-2)
          - so we get n + n-1 + n-2 + n-3 + ...
          - eventually, n == 1 and we return a 1
          - so our final sum is: n + n-1 + n-1 + n-3 + ... + 1, which is what we wanted
          
  • show Powers demo
       - we want to calculate base to the power n
       - how can we do this?
          - basic idea is that we want to multiply 1 times base n times
       - iteratively:

          private double itPower(double base, long n){
             double ans = 1.0;
              while (n > 0) {
                 ans = ans * base;
                 n--;
              }
       
             return ans;
          }

       - recursively:
          - how can we define this recursively (in words)? Remember, just assume you have a method that does what you want it to do, but for smaller problems
             - the base^n is base times base^(n-1)
          - what is our recursive case:
             - power(base, n) = base * power(base, n-1)
          - what is our base case
             - when n == 0 we should just return 1
             - alternatively, when n == 1, we could just return base
             - either one is fine! what would be the difference?
          - write the method:
          
          private double power(double base, long n) {
             if (n == 0) {
                return 1;
             } else {
                return base * power(base, n - 1);
             }
          }

          - why does this work?
             - first we call it with base and n
             - we return base times whatever is returned by power(base, n-1)
             - which returns base times whatever is returned by power(base, n-2)
             - so we best base * base * base * ...
             - eventually, n == 0 and we return 1, so we get:
             - base * base * base * ... * base * 1, where base is multiplied n times since each time we reduce n by 1

  • show Hanoi demo
       - called towers of hanoi
       - invented in 1883 by French mathematician Edouard Lucas (http://en.wikipedia.org/wiki/Tower_of_Hanoi)
       - simple game:
          - move the tower from the left side to the right
          - you may only move one disc at a time
          - you may only place a smaller disc on top of a larger disc
       - how do you solve this? Recursion!
          - harder to solve iteratively
       - how can we define this recursively (in words)?
          - to solve the puzzle:
             - move the top n-1 discs to the center peg
             - move the bottom disk to the right peg
             - move the n-1 discs on the center peg to the right peg
          - can we generalize this?
             - three pegs
                - current
                - destination
                - other
             - want to move n discs from current to destination
                - move top n-1 discs from current to other
                - move bottom disc to destination
                - move n-1 discs from other discs to destination

  • Lab 8: Scribbler
       - another recursion lab
       - can work in pairs again (e-mail me sooner than later if you'd like a partner, or I can pair you up in the lab, but you'll do your design separately then)
       - look at the demo: how are we doing this?
          - define a recursive structure, ScribbleCollection, similar to DraggableChain and ChainRection
          - what is the recursion in words?
             - a ScribbleCollection is a ScribbleIFC, with another ScribbleCollection (rest)
       - don't get confused by the fact that Scribble is also a recursive object. Just think of it as any other object.

  • show FallingLeaves demo
       - we saw this before
       - how does it work?
          - we have a tree that is an ActiveObject, that generates some number of leaves, which are also ActiveObjects
          - Tree class randomly picks between the two different leaf options
          - each time we click, we create a new Tree

  • review FallingLeaves code
       - specifically, look at run method in the Tree class

  • show FallingObjects demo
       - We now have not only falling leaves, but also falling hail
       - How would we modify the code?
          - we could try and modify the FallingLeaves class to support the addition of the hail
             - this would make the code much more complicated
             - would not be good object oriented design
          - a better way is to add a new Hail class
             - create the Hail class
             - change the Tree class to have another random option
             - the hail class would look very similar to the FallingLeaf class except with FilledOval instead of a VisibleImage
                - if you ever find yourself doing a lot of copy and pasting when programming, there's probably a better way to do it!

  • inheritance
       - Java has what's call class inheritance
       - for a class to "inherit" from another class, we use the keyword "extends"
       - where have we seen this so far?
          - extends WindowController
          - extends ActiveObject
       - when a class "extends" another class, it inherits the attributes and behaviors from the parent class
          - the extending class is called the child class or the subclass
          - the class being extended is called the parent class or the superclass
          - the subclass inherits all of the attributes from the parent class, that is all of the non-private methods and variables
             - private methods are only visible within a class
             - this is where the "canvas" variable comes from, we inherit it
       - we've seen public and private scopes for variables and methods, for inheritance, we need one more: protected
          - why do we need another scoping classification?
             - private is only visible within the class
             - public is visible to everyone
          - protected gives us a middle ground, where they're not visible to everyone, but are visible to subclasses

  • a simple inheritance example

    public class Ball{
       public Ball(){
          // some code
       }   

       public bounce(){
          // some code
       }

       public setSize(double d){
          // some code
       }

    }

    public class BasketBall extends Ball{
       public BasketBall(){
          // some code
       }

       public shoot(){
          // some code
       }
    }
       
       - Say we declare a new object of type BasketBall:
          BasketBall bball = new BasketBall()

       - all of the following would be appropriate:
          - bball.shoot()
          - bball.bounce()
          - bball.setSize(10)

  • how can we use inheritance to help us in our hail/leaf example?
       - look at FallingObject class in FallingObjects code
          - represents a generic falling object
             - we use the Drawable2DInterface to allow it the falling object to be a variety of different things
             - note that it is protected, why?
                - subclasses will need to define the actual object, i.e. with a "new" statement
          - constructor just specifies the speed and the stopping height
          - run method
             - moves the object down the screen and then removes it when it gets to the bottom
          - notice that this class does NOT define "object"
             - what would happen if we created a new FallingObject?
                - we'd get a null pointer exception
       - how does this class help us then?
          - we can inherit from this class!
       - look at FallingLeaf class
          - extends FallingObject
          - the "super" keyword allows us to call the constructor of the parent, superclass
             - must be the first line in the constructor
          - create a new VisibleImage and associate it with the "object" variable that we inherited from FallingObject
          - where is the run method?
             - we don't need one... we inherit it from the FallingObject class
       - what will the Hail class look like?
          - extends FallingObject
          - create a new FilledOval for object (rather than a VisibleImage)

  • benefits of inheritance
       - saves us from having to write code multiple times
       - makes shared behavior explicit
       - has the code in one place in case we decide to change it

  • show FallingObjectsWithTomatoRun demo
       - what do we need to change?
          - add a Tomato class that extends FallingObject
       - can we simply extend FallingObject and use the generic run method?
          - the run method in FallingObject removes the object from the canvas when it reaches the bottom
          - we want do want to remove the object, but also want to create a "splat" where the tomato lands
       - in the run method for Tomato:
          - do the normal FallingObject run
          - then create a new red FilleOval at the bottom for the splat
       - look at Tomato class in FallingObjectsWithTomatoRun code
          - constructor is as we'd expect
          - the run method is what is called "overridden"
             - when the subclass defines a method with the same name and parameters, the method is overridden
                - instead of calling the parents method, it will call the classes method
          - often, when we override a method, we just want to alter the behavior of the method
             - super.run() calls the run method of the superclass
             - in general, super.methodName(), will call methodName of the super class
          - what does the run method do?
             - calls the run method of the superclass (i.e. FallingObject)
                - this will cause the original red, FilledOval to fall and then be removed when it reaches the bottom
             - create the splat

  • show FallingObjectsWithCows demo
       - we've added a two more classes
          - Cow (representing the Williams mascot, which is named Ephelia)
          - Cecil (representing the Pomona mascot)
       - how are these new classes related to the Tomato class?
          - like the tomato class, their run method has two stages:
             - fall down the screen
             - do something when they hit the bottom
       - how can we implement these?
          - we could do the same thing we did for the Tomato class...
          - better way is to add a hitBottom method in the FallingObject class

  • look at FallingObjectsWithCows code
       - look at the FallingObject class
          - we've made an explicit method called hitBottom that simply removes the object from the canvas
          - how does this help us?
             - classes that extend this class can override that method
          - why is it protected?
             - if we made it private, then we couldn't override it
       - what will the Cecil and Cow classes look like?
          - like the others, in the constructor, create a new VisibleImage, etc.
          - will only have to override the hitBottom method to change the functionality!
          - don't need to override the run method