Generic Packages
Introduction to Generic Packages
Reminder: Formal and Actual Parameters
- Before we get into the details of generics, we need to remember
the difference between formal and actual parameters for methods and
procedures.
- The formal parameters of a procedure are the parameters
given in the declaration of the procedure.
- The actual parameters are
the variables or values that are used when the procedure is called.
- Of
course, each actual parameter is associated with a specific formal
parameter when the procedure is called.
Generic packages: Motivation
- Question: Can we use the integer stack package for floats?
with intstkpkg;
s: intstkpkg.stacktype;
i: integer;
f: float;
begin
push(3, s);
push(4.0, s)
f := top(s);
pop(s);
i := top(s);
Consider a float stack package based on the integer stack package
What are the differences
Need a parameter for the parameter that allows us to specify the TYPE of item that will be put on
the stack
The rest of the code is the same
Generic Stack Package
Terminology: Instantiate
- Terminology: Instantiate a generic package
- Creates an instance of a package
- Compare to: instantiate a class
- Creates an object - that is, an instance of a class
- When does each happen?
Strong Typing and Generic Packages
- The Integer and Float Stack Packages are strongly typed, based on the types of the package parameter
- Consider this code:
intStk: IntStkPkg.Stack;
fltStk: IntStkPkg.Stack; -- Should have been FltStkPkg
i: Integer;
f: float;
begin
push(1, intStk); -- Does each pair of statement compile?
push(1.0, fltStk);
i := top(intStk)
f := top(fltStk)
push(1, fltStk);
push(1.0, intStk);
f := top(intStk)
i := top(fltStk)
Later we will compare this with Java (pre 1.5, ie pre Java 5)
Generic Packages vs Regular Packages
- Generic packages are "cookiecutter" packages that can be
used to create other (regular) packages.
- Generic packages are different from regular packages in two
ways:
- You use them to create regular packages. A given generic
package can be used to make as many packages as you want.
- Generic packages can have parameters that are given
values
when the generic package is used to create a regular package. This
means that by varying the parameters, a given generic package can be
used to create different regular packages that have different
properties.
Type Parameters
- A key point about the parameters is that typically they are
type parameters!
- Just like an Integer parameter to a
procedure
must be given an integer value when the procedure is called, a type
parameter must be given a type
when the generic package is used to create a regular package.
- This
means
that what is given to a type parameter is a type (eg Integer) not a
value (eg 3). By giving types for the generic parameters, new packages
are created which are tailored to specific types.
Limited Private
- Context: in the generic and non-generic stack packages, the stack type is declared as limited
type stack is limited private;
The Problem: What happens here:
s, t: stack;
begin
push(12, s);
push(13, s);
push(12, t);
push(13, t);
if s = t then ..
One solution: redefine =
Another solution: eliminate = as an operation
A limited type is not allowed to use = or :=
- Thus, both of these are illegal:
if s = t then ..
s := t;
But = may be redefined, is desired
We will discuss more about motivation for limited after we have covered pointers
Example Generic Packages
Enumeration IO Generic Package
- Remember this from our discussion of Enumerated Types
- enumeration_io is a generic package that takes one type, namely the enumerated type for which to create a new I/O procedures.
- Enumeration_IO is used to create a new package that does I/O for the enumerated type color.
- How Enumeration_IO is declared:
-
(<>)
specifies that the parameter can be any discrete type (eg any integer
or enumeration type)
- You can see the entire package
specification
here
Generic Queue ADT
Generic Packages and Other Languages
Defining the Problem
- What do generic packages provide:
- Generics allow us to create Abstract Types (eg stack, queue) that
- Can be instantiated for any type (thus reusing code)
- Provide strong typing
- Avoid having to write duplicated code
- Question: How do we get these same facilities in other languages?
Java (pre 1.5, ie pre Java 5)
- How do we get similar capabilities (ie type checked stacks of different types) in Java
- How about this:
- class IntStack{...}
- class FloatStack{...}
- Gives type checking, but duplicates code
Java (pre 1.5, ie pre Java 5) Continued - Stack of Objects
- How about this: Stack of Objects:
class ObjStack{
private Object[] els = new Object[1000];
private int top = -1;
void push(Object o){this.els[++this.top} = o;}
void pop(){this.top--}
Object top(){return this.els[this.top]
}
Less duplicated code, but what about type checking?
A client:
ObjStack s = new ObjStack();
s.push(new Integer(3))
Integer i = s.top(); // Okay?
ObjStack t = new ObjStack();
t.push(new Float(4.0))
t.push(new Integer(3)...)
Integer j = t.top(); // Okay?
t.pop();
Integer k = t.top(); // Okay?
Compare the type checking here with Ada's type checking
Java 1.5 (ie 5) - Parameterized Types
class Stack<T>{
private T[] els = new T[1000];
private int top = -1;
void push(...){...}
void pop(){...}
T top(){...}
}
...
// Client
Stack<Integer> s = new Stack<Integer>();
s.push(new Integer(3))
Integer i = s.top(); // Cast required?
Stack<Float> t = new Stack<Float>();
t.push(new Float(4.0))
t.push(new Integer(3)...) // Okay?
Can we have a stack of primitive types?
Other Languages: C++
- C++ eventually (circa 1990) introduced templates
- Influenced by Ada generics
- Example (based on example from Stack Overflow):
// Parameterized class
template<typename T, size_t N>
class Array {
// Function data() returns a pointer to a T
public:
T * data();
// An array of N elements of type T is a private member of the class
private:
T elems[ N ];
};
// Implementation of function data()
template<typename T, size_t N>
T * Array<T>::data() {
return elems;
}
// Client:
typedef Array<int, 100> MyArray;
MyArray anArray;
int * somearr = anArray.data(); // Access data in anArray
Some Many complain about C++ templates and code bloat
Generic Child Packages
The Problem
- What if we want to create a child package for a generic package
- Does the child need to be generic?
- How is a generic child instantiated?
Generic Child Packages
- Here are some notes on creating child packages of generic packages