WEEK12: defining our own classes/object-oriented programming
---------------------------------------------------------------
 M: classes

QUIZ 6 will be next Friday!
Lab 10 AND 11 will be due next Saturday (Dec 7)


OBJECTS REVIEW:

 - we've used objects already:

       cenpt = Point(200,200)
       c1 = Circle(cenpt, 100)
       c1.setFill("blue")
       c1.draw(win)

   in the above code, cenpt is a Point object, and c1 is a Circle
   object. We also used the Circle class' methods setFill and draw

 - an object is just data *and* functions all together in one "thing"

 - for the above Circle object, the data are the center point, the
   radius (100), and the color. The functions are just the methods
   that do something to the circle (fill it, draw it, move it)

object:   data      +     methods

"abc"     chars           upper()  isalpha()
          size?           lower()  isdigit()
                          starswith()

list      items in list   sort()    count()
          size of list?   append()  index()

Point()   x,y coords      draw(), getX(), getY(), move()

Song()    artist,genre,   play(), getNumPlays()
          num plays, 
          album name,
          year

Pizza()   toppings        eatOneSlice()
          num slices


 - in Python, almost everything is an object. Look at the help info
   for str and list and you can see all of their methods:

>>> help(str)

>>> help(list)


FIRST EXAMPLE of WRITING A NEW CLASS:

 - let's write a silly Pizza class

 - terms/syntax/definitions...

       __init__     the constructor method -- called when we create
                    a new variable of this type (ex: p1 = Pizza("cheese"))
       __str__      the print method -- called when we print a
                    variable of this type (ex: print p1). This method must
                    RETURN a string!
       self         the first parameter to any method. This is just a reference
                    to the object on which the method is acting (if I say
                    p1.move(), self = p1)
       accessors    methods that get or access the object data (like getTopping())
       mutator      methods that change object data (like eatOneSlice() method)

if __name__ == '__main__':         this line is for testing your new class. if your
  # add your test code here        new class is imported, this code will not be run.
                                   if your class is run directly (like "python pizza.py"),
                                   then this test code *will* be executed.

"""triple-quote comments"""        also note the use of the triple-quoted comments in letter.py!
                                   if you say "import letter" and then "help(letter)" the documentation
                                   you see *is* the triple-quoted comments!!

CLASS WRITER does this (file = pizza.py):

class Pizza(object):
  """pizza class...allows creation and eating of virtual pizzas"""

  def __init__(self, topping):
    """constructor for pizza class...requires topping choice"""

    self.topping = topping
    self.slices = 8

  def eatSlice(self):
    """user eats one slice, if available"""

    if self.slices > 0:
      self.slices = self.slices - 1

  def __str__(self):
    """return string we want printed when object is printed"""

    return "%s pizza -- slices left: %d" % (self.topping, self.slices)

if __name__ == "__main__":
  # test code here

  p1 = Pizza("cheese")
  print p1
  p2 = Pizza("ham")
  print p2


CLASS USER does this (file = pizzaapp.py):

from pizza import *

p1 = Pizza("cheese")
print p1
p2 = Pizza("ham")
p2.eatSlice()
print p2


YOUR TURN: write the patient.py file that goes with this program:

$ cat hospitalwing.py 
"""
hospital wing program...show use of patient class

J. Knerr
Fall 2013
"""

from patient import *

####################################################

def main():

  draco = Patient("Draco Malfoy", 13)
  harry = Patient("Harry Potter", 13)
  draco.ageOneYear()
  harry.addDisease("dragon pox")
  print draco
  print harry

  print "="*30

  draco.addDisease("spattergoit")
  draco.addDisease("pink eye")
  draco.addDisease("vanishing sickness")
  harry.cure()
  print draco
  print harry


####################################################

main()


WHY ARE WE DOING THIS???

 - object-oriented programming (OOP) is a different way to program. Some
   think it is better (easier to maintain, cleaner) for large, complicated programs.

 - if you write a good general class, it's easy to use it over and over
   in many programs (code reuse == good)

 - some think OOP is more intuitive, since the objects you create usually
   represent real-life objects (cards, planets, students, etc)

 - INTERFACE between class writer and program writer