6.4. Composite Classes, Revisited

You might recall that when we talked about the fields of the Student class back in Chapter 3, we held off on assigning types to a few of the items shown in Table 6-1.

Table 6.1. Proposed Data Structure for the Student Class
Field NameData Type
namestring
studentIDstring
birthdateSystem.DateTime
addressstring
majorstring
gpadouble
advisorProfessor
courseLoad???
transcript???

Armed with what we now know about collections, we can go back and assign types to the courseLoad and transcript fields.

6.4.1.

6.4.1.1. courseLoad

The courseLoad field is meant to represent a list of all Course objects that the Student is presently enrolled in. So, it makes perfect sense that this field be declared to be simply a standard collection of Course objects!

public class Student
{
  private string name;
  private string studentId;
  // etc.
  private 
							CollectionType 
							courseLoad; // of Course objects 

// etc.

6.4.1.2. transcript

The transcript field is a bit more challenging. What is a transcript in real-world terms? It's a report of all of the courses that students have taken since they were first admitted to this school, along with the semester in which each course was taken, the number of credit hours that each course was worth, and the letter grade received for the course. If we think of each entry in this list as an object, we can define them via a TranscriptEntry class, representing an abstraction of a single-line item on the transcript report, as follows:

public class TranscriptEntry
{
  // One TranscriptEntry represents a single line item on a transcript report.

private Course courseTaken;
  private string semesterTaken;  // e.g., "Spring 2009"
  private string gradeReceived;  // e.g., "B+"

  // Details omitted ...

  // Note how we "talk to" the courseTaken object via its methods
  // to retrieve some of this information (delegation once again!).
  public void PrintTranscriptEntry() {
    // Reminder:  	 is a tab character.
    Console.WriteLine(courseTaken.GetCourseNumber() + "	" +
      courseTaken.GetTitle() + "	" +
      courseTaken.GetCreditHours() + "	" +
      gradeReceived);
  }

  // other methods TBD
}

Note that we're declaring one of the fields of TranscriptEntry to be of type Course, which means that each TranscriptEntry object will maintain a reference to its corresponding Course object. By doing this, the TranscriptEntry object can avail itself of the Course object's title, course number, or credit hour value (needed for computing the GPA)—all privately encapsulated in the Course object as fields—by calling the appropriate methods on that Course object as needed.

Back in the Student class, we can now define the Student's transcript field to be a collection of TranscriptEntry objects. We can then add a PrintTranscript method on the Student class, the code for which is highlighted here:

public class Student
{
  private string name;
  private string studentId;
  // etc.
  private 
							CollectionType 
							transcript; // of TranscriptEntry objects 

  // Details omitted ...

  public void PrintTranscript() { 
							// Pseudocode. 
							for ( each TranscriptEntry t in transcript ) { 
							t.PrintTranscriptEntry(); 
							} 
							} 
}

6.4.1.3. transcript, Take 2

Alternatively, we can use the technique of creating a wrapper class called Transcript to house some standard collection type:

public class Transcript
{
    private List<TranscriptEntry> transcriptEntries; // of TranscriptEntry objects
    // other fields omitted from this example

    // Pseudocode.
    public void AddTranscriptEntry(arglist) {
      insert new entry into List -- details omitted
    }

    // We've transferred the logic of the Student class's
    // PrintTranscript method into THIS class instead.
    public void Print(string filename) {
      // Pseudocode.
      for (each TranscriptEntry t in transcript) {
        t.PrintTranscriptEntry();
      }
    }

    // etc.
  }

We then can go back to the Student class and change our declaration of the transcript field from being a standard collection type to being of type Transcript:

public class Student
{
  private string name;
  private string studentId;
  // etc.
  private Transcript transcript;  // an ENCAPSULATED collection of
							// TranscriptEntry objects
  // etc.

We can then turn around and simplify the PrintTranscript method of the Student class accordingly:

public class Student
{
  // Details omitted.

  public void PrintTranscript() {
    // We now delegate the work to the Transcript field
							transcript.Print();
  }

  // etc.

This "take two" approach of introducing two new classes/abstractions—TranscriptEntry and Transcript—is a bit more sophisticated than the first approach, in which we introduced TranscriptEntry only as an abstraction. Also, this second approach is "truer" to the object paradigm, because the Student class needn't be complicated by the details of how Transcripts are represented or managed internally—those details are hidden inside of the Transcript class, as they should be.

6.4.1.4. Our Completed Student Data Structure

Table 6-2 illustrates how we've taken full advantage of collections to round out our Student class definition.

Table 6.2. Rounding out the Student Class' Data Structure with Collections
Field NameData Type
namestring
studentIDstring
birthdateSystem.DateTime
addressstring
majorstring
gpadouble
advisorProfessor
courseLoadStandard type collection of Course objects
transcriptEither a standard type collection of TranscriptEntry objects or (preferred) Transcript

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset