CSC 153 Grinnell College Spring, 2005
 
Computer Science Fundamentals
Laboratory Exercise
 

Introduction to Object-Oriented Programming

Abstract

The concepts of classes and objects provide a different perspective for solving problems than the functional approach we have used up to this point in the course. The functional approach is concerned primarily with applying procedures to data in order to get results; solutions arise as a sequence of functional transformations. In contrast, object-oriented programming identifies classes, objects, and their relationships as the basis for problem solving.

This laboratory exercise introduces some ideas of objects and classes in the Object-Oriented Programming paradigm, and considers how these ideas may be implemented in Scheme.

Introduction

Object-Oriented Programming (OOP) provides a different way of approaching problems than the functional paradigm that we have been using. In OOP we will create objects that make their own decisions in response to messages sent to them. The objects are self-contained and in control of themselves, but generally sit idle until they are told to act. Their responses to such messages can be of countless forms, but some reasonable ones might be similar to those given by someone who gets a credit card bill in the mail. She could pay the bill in full if she has enough money; send a message back saying, "I already paid that bill;" pay the minimum required payment for that month; or send a message to her lawyer to take legal action regarding that bill. Any changes the object makes will affect only itself and not other objects or the outside world.

Since programming problems often consist of many instances of similar data, it is often useful to us define classes of objects, groups in which each member has the same structure as each other member, but the details contained in any one object's structure change independently from those in any other object's structure. Any object in the class can be told to perform an operation by being sent a message telling it to act. The type of messages can be particular to a class or can be available to several different classes of objects.

Example of an Object

Each one of you has a couple of phone directories in your dorm room that were provided by the college, one student directory and one faculty directory. The following object is a small portion of the faculty directory, in which one could look up various pieces of information. Let's include listings for all of the professors in Grinnell's Math/Computer Science Department, in which their names and specializations within the department are the only bits of information that appear right now.

  1. Load the following class definition and faculty directory object:
    >  (load "/home/walker/153/labs/intro-oop.ss")
    

    Send the directory the following messages to see how it responds:

    > (directory 'listing) 
    > (directory 'listing "CS") 
    > (directory 'listing "Math") 
    > (directory 'listing "English") 
    > (directory 'department "Rebelsky") 
    > (directory 'department "Wolf") 
    > (directory 'department "Walker") 
    > (directory 'department "Jones") 
    

    How did the object respond to each message and why?

An Object-Oriented Problem: A Student Database

The registrar's office of a college wishes to implement a database to keep track of its students. The office is concerned with the following pieces of information for each student: graduation year, number of credits earned in to date, courses currently enrolled in, and major and advisor, if the student has declared her major.

Previously we might have input each part of this data into separate fields of a class, but now we will approach the problem by letting each student, represented by an object in the database, keeps track of things herself. The state of a certain object consists of the details each student is keeping track of.

  1. What comprises the state of each student object in our example?

Solving the problem for multiple students:

Unlike a directory, where we might have a list of students, each with these several attributes, we wish to create separate entities of the type student. Each entity should operate independently of the others. If the department only had one student, we would only need to implement one object, but since there are many students, and new ones each semester, we always need to be able to expand the database by creating or "instantiating" new student objects.

To use a group of similar entities, in this case students, we define a class of them. The class definition will allow us to create new students, each a separate entity with the proper structure.

The following class definition is set up so that a student can tally credit for completed courses and can declare the Math or Computer Science major with one of the available Math or CS advisors. Each object will accept the messages declare, completed, show_credits, show_major, and show_advisor with appropriate arguments, and will take the appropriate action.

(define student
  (lambda (new-name new-major new-advisor new-credits)
    (let ((name new-name)       ;; the class data
          (major new-major)
          (advisor new-advisor)
          (credits new-credits))
      (letrec                   ;; the class methods
        ((check-dept ; check if any department on dept-str matches given dept
            (lambda (dept dept-str)
               (let* (;; add initial and final spaces to check full dept names
                      (check-dept (string-append " " dept " "))
                      (check-str (string-append " " dept-str " "))
                      (check-len (string-length check-str)))
                  (let loop ((start-pos 0)
                             (end-pos (string-length check-dept)))
                      (cond ((> end-pos check-len) #f)
                            ((string-ci=? check-dept 
                                  (substring check-str start-pos end-pos))
                                #t)
                            (else (loop (+ start-pos 1) (+ end-pos 1))))))))
         (declare
           (lambda (prof desired-major)
             (if (check-dept desired-major (directory 'department prof))
                 (begin
                    (set! advisor prof)
                    (set! major desired-major))
                 (begin
                    (display "Student ")
                    (display name)
                    (display ":  sorry, ")
                    (display prof)
                    (display " is not listed as a professor for your major.")))))
         (completed
            (lambda (new_credits)
               (set! credits (+ credits new_credits))
               credits))
          ) ;; end of local definitions

        (lambda (op . parameters)
           (case op       ;; process external requests   
               ((declare)       (declare (car parameters)(cadr parameters)))
               ((completed)     (completed (car parameters)))
               ((show_credits)  credits)
               ((show_advisor)  advisor)
               ((show_major)    major)
               (else "unknown operation")
           )
        )
      )
    )
  )
)

  1. Copy the above code into Scheme.

  2. Define some objects with the commands:

    > (define dick (student "Dick"  "undeclared" "staff" 0)) 
    > (define jane (student "Jane"  "undeclared" "staff" 0)) 
    > (define rick (student "Dick"  "undeclared" "staff" 0)) 
    > (define mary jane) 
    

    This sequence of definitions will create separate objects for Dick and Jane as undeclared majors with unspecified advisors and zero credits. It will also define Rick as an object masquerading as Dick, and make Mary an alias that Jane uses.

  3. Input the following commands and describe what they do to the objects, in terms of output to the screen and what happens internally to the object.

    > (jane 'declare "Walker" "CS") 
    > (dick 'completed 4) 
    
  4. Check that the appropriate objects made the appropriate changes with the commands:

    > (jane 'show_major) 
    > (dick 'show_major) 
    > (rick 'show_major) 
    > (mary 'show_major) 
    
    > (jane 'show_advisor) 
    > (dick 'show_advisor) 
    > (rick 'show_advisor) 
    > (mary 'show_advisor) 
    
    > (jane 'show_credits) 
    > (dick 'show_credits) 
    > (rick 'show_credits) 
    > (mary 'show_credits) 
    

    Note that Jane still has no credits and Dick is undeclared. Why is this? What are the states of Rick and Mary?

  5. Now have Rick declare his major and let Mary complete a 4 credit course:

    >(rick 'declare "Jepsen"  "Math") 
    >(mary 'completed 4) 
    

    Who are Dick's and Rick's advisors now? What about their majors? How many credits do Mary and Jane have? Explain each result.

    Why do Dick and Rick appear different now, when they were defined with identical states? If not state, then what is the factor that distinguishes one object from another?

  6. Add arguments to the class declaration such that new objects hold the student's graduation year and the course numbers (e.g. "CSC153" and "MAT218"; use a list) that the student is enrolled in during the current semester. Add methods to the listing such that the student can input his graduation year and add or drop a course. Create a new student object with your name to test these new methods.

  7. Send some messages to Mary, Dick or Jane telling them to act according to these new methods. How do they respond and why?

  8. Suppose the department wished also to include the professors in the database, with each one teaching certain courses, advising certain students, and pursuing certain professional projects. List specifications, including state, behavior, and identity for a possible class of professors engaged in such activities.


This document is available on the World Wide Web as

http://www.cs.grinnell.edu/~walker/courses/153.sp05/labs/lab-intro-oop.shtml

created March 11, 1998 by Scott G. Barkley
updated April 1, 1998 by Scott G. Barkley
updated April 9, 1998 by Henry M. Walker
further updated January 16, 2000
last revised February 3, 2005
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at walker@cs.grinnell.edu.