Inventing Our Own Collection TypesAs mentioned earlier, different types of collections have different properties and behaviors. You must therefore familiarize yourself with the various built-in collection types available for your OO language of choice, and choose the one that is the most appropriate for what you need in a given situation. Or, if none of them suit you, invent your own! This is where we start to get a real sense of the power of an OO language: since we have the ability to invent our own abstract data types, we have free rein to define our own collection types, because these, after all, are merely classes.There are several ways to create one's own collection type:
Let's discuss each of these approaches in turn.Approach #1: Create a Brand-New Collection Type from ScratchCreating a brand new collection class from scratch is typically quite a bit of work, and since most OO languages provide such a wide range of predefined collection types, it's almost always possible to find a preexisting collection type to use as a starting point, in which case one of the following two approaches would be preferred.Approach #2: Extend a Predefined Collection ClassIn the following example, we extend the built-in ArrayList class to create a collectionclass called MyStringCollection:using System.Collections;public class MyStringCollection : ArrayList{ // We inherit all of the attributes and methods of a standard ArrayList // "as-is," then define a few attributes and methods of our own. private string longestStringAddedSoFar; // Define a completely new method. public void AddAString(string s) { // Add the string to the collection using the Add() method that we've // inherited from ArrayList.Add(s); // Pseudocode. //compare length of s to the length of the longest string inserted so far, //as recorded by attribute longestStringAddedSoFar; // Pseudocode. if (s is longer than longestStringAddedSoFar) { // Remember this fact! longestStringAddedSoFar = s; } }}
This approach works well if we simply intend to add a few completely new features (attributes, methods), inheriting the methods and attributes of the parent class "as is."If we plan on overriding any of the inherited methods, however, we must remember to invoke the parent's version of the code first, via the base keyword, as we learned to do in Chapter 5:using System.Collections;public class MyStringCollection : ArrayList{ private string longestStringAddedSoFar; // In this case, we choose to override the Add() method of ArrayList. public override void Add(Object s) { // Add the string to the collection using our parent's version of the // Add() method. base.Add(s); // Pseudocode. compare length of s to the length of the longest string inserted so far as recorded by attribute longestStringAddedSoFar; // Pseudocode. if (s is longer than longestStringAddedSoFar) { // Remember this fact! longestStringAddedSoFar = s;preetiaswalPassword:aditya } }}
By invoking base. Add() as the first step in our overridden Add() method, we're ensuring that we're doing everything that our parent ArrayList class does when adding an item to its internal collection, without having to know the details of what is happening behind the scenes , before we go on to do something extra: namely, to track the longest such string item in this particular case.Approach #3: Create a "Wrapper" Class to Encapsulate a Predefined Collection TypeBy creating such a wrapper class, we are able to hide some of the details involved with manipulating the collection. This is a nice compromise position, and we'll illustrate how one goes about doing this with a specific example. Let's say we wanted to invent a new type of collection called an EnrollmentCollection, to be used by a Course object to manage all of its enrolled Student objects. We could take advantage of information hiding and encapsulation to"hide"a standard collection object-say, a C# ArrayList, which as mentioned earlier is C#'s implementation of an ordered list collection-inside of our EnrollmentCollection class, as an attribute. We'd then provide.
These methods' logic can be as sophisticated as we wish for it to be-the method bodies are ours to control! The following example uses heavy doses of pseudocode to give you a sense of what we might actually program these methods to do for us; we'll see plenty of real C# collection manipulation (ArrayLists in particular) in the SRS code examples in Part Three of the book.public class EnrollmentCollection{ // "Hide" a standard C# collection object inside as a private attribute. // We'll be storing Student objects in this collection. private ArrayList students; // Constructor. public EnrollmentCollection() { // Instantiate the encapsulated ArrayList instance. students = new ArrayList(); } // Methods to add a student ... public bool Enroll(Student s) { // First, make sure that there is room in the class (pseudocode). if (adding this student will exceed course capacity) { return false; } // Next, make sure that this student isn't already enrolled // in this class (pseudocode). if (student is already enrolled) { return false;}// Verify that the student in question has met// all necessary prerequisites (pseudocode).if (some prerequisite not satisfied) { return false; }// If we made it to here, all is well!// Add the student to the ArrayList by calling its Add() method.// (This is an example of delegation, a concept that we discussed// in Chapter 4.)students.Add(s);return true;} // ... and to remove a student. public bool Drop(Student s) {// First make sure that the student in question// is actually enrolled (pseudocode).if (student is not enrolled) {return false;}// Remove the student from the ArrayList by calling the Remove()// method. (Another example of delegation.)students.Remove(s);return true;} public int GetTotalEnrollment() { // Access and return the size of the ArrayList. (Delegation yet again!) return students.Count; } public bool IsEnrolled(Student s) { // More delegation! if (students.Contains(s)) { return true; } else { return false; } }}