0% found this document useful (0 votes)
10 views5 pages

02 Parameterized Abstract Data Types

The document discusses abstract data types (ADTs) and encapsulation constructs, focusing on the implementation of stack structures in Ruby, C++, Java 5.0, and C# 2005. It highlights the flexibility of Ruby's dynamic typing and the introduction of parameterized types in C++ and Java 5.0, which allow for generic collections that can store various data types. Additionally, it covers the limitations and advantages of these implementations, including the ability to define user-generated generic classes.

Uploaded by

prow8273
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views5 pages

02 Parameterized Abstract Data Types

The document discusses abstract data types (ADTs) and encapsulation constructs, focusing on the implementation of stack structures in Ruby, C++, Java 5.0, and C# 2005. It highlights the flexibility of Ruby's dynamic typing and the introduction of parameterized types in C++ and Java 5.0, which allow for generic collections that can store various data types. Additionally, it covers the limitations and advantages of these implementations, including the ability to define user-generated generic classes.

Uploaded by

prow8273
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

496 Chapter 11 Abstract Data Types and Encapsulation Constructs

# The following pop should produce an


# error message - stack is empty
myStack.pop

Recall that the notation #{variable} converts the value of the variable to a
string, which is then inserted into the string in which it appears. This class
defines a stack structure that can store objects of any type.

11.4.5.4 Evaluation
Recall that in Ruby, everything is an object and arrays are actually arrays of
references to objects. That clearly makes this stack more flexible than the sim-
ilar examples in C++ and Java. Furthermore, simply by passing the desired
maximum length to the constructor, objects of this class could have any given
maximum length. Of course, because arrays in Ruby have dynamic length, the
class could be modified to implement stack objects that are not restricted to
any length, except that imposed by the machine’s memory capacity. Because the
names of class and instance variables have different forms, Ruby has a slight
readability advantage over the other languages discussed in this section.

11.5 Parameterized Abstract Data Types


It is often convenient to be able to parameterize abstract data types. For
example, we should be able to design a stack abstract data type that can store
any scalar type elements rather than be required to write a separate stack
abstraction for every different scalar type. Note that this is only an issue for
static typed languages. In a dynamic typed language like Ruby, any stack
implicitly can store any type elements. In fact, different elements of the stack
could be of different types. In the following three subsections, the capabilities
of C++, Java 5.0, and C# 2005 to construct parameterized abstract data types
are discussed.

11.5.1 C++
To make the example C++ stack class of Section 11.4.1 generic in the stack size,
only the constructor function needs to be changed, as in the following:

Stack(int size) {
stackPtr = new int [size];
maxLen = size - 1;
topSub = -1;
}

The declaration for a stack object now may appear as follows:

Stack stk(150);
11.5 Parameterized Abstract Data Types 497

The class definition for Stack can include both constructors, so users can
use the default-size stack or specify some other size.
The element type of the stack can be made generic by making the class
a templated class. Then, the element type can be a template parameter. The
definition of the templated class for a stack type is as follows:

#include <iostream.h>
template <typename Type> // Type is the template parameter
class Stack {
private:
Type *stackPtr;
int maxLen;
int topSub;
public:
// A constructor for 100 element stacks
Stack() {
stackPtr = new Type [100];
maxLen = 99;
topSub = -1;
}
// A constructor for a given number of elements
Stack(int size) {
stackPtr = new Type [size];
maxLen = size - 1;
topSub = -1;
}
~Stack() {delete stackPtr;}; // A destructor
void push(Type number) {
if (topSub == maxLen)
cout << "Error in push–stack is full\n";
else stackPtr[++ topSub] = number;
}
void pop() {
if (empty())
cout << "Error in pop–stack is empty\n";
else topSub --;
}
Type top() {
if (empty())
cerr << "Error in top--stack is empty\n";
else
return (stackPtr[topSub]);
}
int empty() {return (topSub == -1);}
}

C++ templated classes are instantiated to become typed classes at compile


time. For example, an instance of the templated Stack class, as well as an
instance of the typed class, can be created with the following declaration:

Stack<int> myIntStack;
498 Chapter 11 Abstract Data Types and Encapsulation Constructs

However, if an instance of the templated Stack class has already been created
for the int type, the typed class need not be created.

11.5.2 Java 5.0


Java 5.0 supports a form of parameterized abstract data types in which the
generic parameters must be classes. Recall that these were briefly discussed in
Chapter 9.
The most common generic types are collection types, such as LinkedList
and ArrayList, which were in the Java class library before support for generics
was added. The original collection types stored Object class instances, so they
could store any objects (but not primitive types). Therefore, the collection
types have always been able to store multiple types (as long as they are classes).
There were three issues with this: First, every time an object was removed from
the collection, it had to be cast to the appropriate type. Second, there was no
error checking when elements were added to the collection. This meant that
once the collection was created, objects of any class could be added to the col-
lection, even if the collection was meant to store only Integer objects. Third,
the collection types could not store primitive types. So, to store int values in
an ArrayList, the value first had to be put in an Integer class instance. For
example, consider the following code:

//* Create an ArrayList object


ArrayList myArray = new ArrayList();
//* Create an element
myArray.add(0, new Integer(47));
//* Get first object
Integer myInt = (Integer)myArray.get(0);

In Java 5.0, the collection classes, the most commonly used of which is
ArrayList, became a generic class. Such classes are instantiated by calling new
on the class constructor and passing it the generic parameter in pointed brackets.
For example, the ArrayList class can be instantiated to store Integer objects
with the following statement:

ArrayList <Integer> myArray = new ArrayList <Integer>();

This new class overcomes two of the problems with pre-Java 5.0 collections.
Only Integer objects can be put into the myArray collection. Furthermore,
there is no need to cast an object being removed from the collection.
Java 5.0 also includes generic collections for linked-lists, queues, and sets.
Users also can define generic classes in Java 5.0. For example, we could
have the following:

public class MyClass<T> {


. . .
}
11.5 Parameterized Abstract Data Types 499

This class could be instantiated with the following:

MyClass<String> myString;

There are some drawbacks to these user-defined generic classes. For one
thing, they cannot store primitives. Second, the elements cannot be indexed.
Elements must be added to user-defined generic collections with the add
method. Next, we implement the generic stack example using an ArrayList.
Note that the last element of an ArrayList is found using the size method,
which returns the number of elements in the structure. Elements are deleted
from the structure with the remove method. Following is the generic class:

import java.util.*;
public class Stack2<T> {

private ArrayList<T> stackRef;


private int maxLen;
public Stack2() { // A constructor
stackRef = new ArrayList<T> ();
maxLen = 99;
}
public void push(T newValue) {
if (stackRef.size() == maxLen)
System.out.println("Error in push–stack is full");
else
stackRef.add(newValue);
}
public void pop() {
if (empty())
System.out.println("Error in pop–stack is empty");
else
stackRef.remove(stackRef.size() - 1);
}
public T top() {
if (empty()) {
System.out.println("Error in top–stack is empty");
return null; }
else
return (stackRef.get(stackRef.size() - 1));
}
public boolean empty() {return (stackRef.isEmpty());}

This class could be instantiated for the String type with the following:

Stack2<String> myStack = new Stack2<String>();

Recall from Chapter 9, that Java 5.0 supports wildcard classes. For example,
Collection<?> is a wildcard class for all collection classes. This allows
a method to be written that can accept any collection type as a parameter.
Because a collection can itself be generic, the Collection<?> class is in a sense
a generic of a generic class.
500 Chapter 11 Abstract Data Types and Encapsulation Constructs

Some care must be taken with objects of the wildcard type. For example,
because the components of a particular object of this type have a type, other
type objects cannot be added to the collection. For example, consider

Collection<?> c = new ArrayList<String>();

It would be illegal to use the add method to put something into this collection
unless its type were String.
A generic class can easily be defined in Java 5.0 that will work only for a
restricted set of types. For example, a class can declare a variable of the generic
type and call a method such as compareTo through that variable. If the class is
instantiated for a type that does not include a compareTo method, the class cannot
be used. To prevent a generic class from being instantiated for a type that does not
support compareTo, it could be defined with the following generic parameter:

<T extends Comparable>

Comparable is the interface in which compareTo is declared. If this generic


type is used on a class definition, the class cannot be instantiated for any
type that does not implement Comparable. The choice of the reserved word
extends seems odd here, but its use is related to the concept of a subtype.
Apparently, the designers of Java did not want to add another more connotative
reserved word to the language.

11.5.3 C# 2005
As was the case with Java, the first version of C# defined collection classes that
stored objects of any class. These were ArrayList, Stack, and Queue. These
classes had the same problems as the collection classes of pre-Java 5.0.
Generic classes were added to C# in its 2005 version. The five predefined
generic collections are Array, List, Stack, Queue, and Dictionary (the
Dictionary class implements hashes). Exactly as in Java 5.0, these classes
eliminate the problems of allowing mixed types in collections and requiring
casts when objects are removed from the collections.
As with Java 5.0, users can define generic classes in C# 2005. One capability
of the user-defined C# generic collections is that any of them can be defined to
allow its elements to be indexed (accessed through subscripting). Although the
indexes are usually integers, an alternative is to use strings as indexes.
One capability that Java 5.0 provides that C# 2005 does not is wildcard classes.

11.6 Encapsulation Constructs


The first five sections of this chapter discussed abstract data types, which are
minimal encapsulations. This section describes the multiple-type encapsula-
tions that are needed for larger programs.

You might also like