The Type System

The Type System

An object-oriented programming language offers the user a rich collection of types. Starting with atomic types, such as integers, real numbers, booleans, and character strings, one may construct new types by using type constructors. Usually, the type constructors let us build:

1. Record structures. Given a list of types T1,T2, . . . ,Tn and a corresponding list of field names (called instance variables in Smalltalk) f1, f2, . . . , fn, one can build a record type consisting of n components. The ith component has type Ti and is referred to by its field name fi. Record structures are precisely what C or C++ calls "structs", and we shall often use that term in what follows.

2. Collection types. Given a type T, one can build new kinds by applying a collection operator to type T. Different languages use different collection operators, but there are various common ones, including arrays, lists, and sets. Therefore, if T were the atomic type integer, we might construct the collection types "array of integers", "list of integers", or "set of integers."

3. Reference types. A reference to a type T is a type whose values are appropriate for locating a value of the type T. In C or C++, a reference is a "pointer" to a value, that is, the virtual-memory address of the value pointed to.

Of course, record-structure and collection operators can be applied again and again to construct ever more complicated types. For example, a bank might define a type that is a record structure with a first component named customer of type string and whose second component is of type set-of-integers and is named accounts. Such a type is appropriate for associating bank customers with the set of their accounts.

Classes and Objects

A class comprises a type and perhaps one or more functions or procedures (called methods; see below) that can be carried out on objects of that class. The objects of a class are either values of that type (called immutable objects) or variables whose value is of that type (called mutable objects). For instance, if we define a class C whose type is "set of integers", then {2,5,7} is an immutable object of class C, while variable s could be declared to be a mutable object of class C and assigned a value such as {2,5,7}.

Object Identity

Objects are supposed to have an object identity (OID). No two objects can have the same OID, and no object has two different OID's. Object identity has some interesting effects on how we model data. For example, it is necessary that an entity set have a key formed from values of attributes possessed by it or a related entity set (in the case of weak entity sets). However, within a class, we assume we can distinguish two objects whose attributes all have the same values, because the OID's of the two objects are guaranteed to be different.

Methods

Connected with a class there are generally certain functions, frequently called methods. A method for a class C has at least one argument that is an object of class C; it may have other arguments of any class, including C. For instance, associated with a class whose type is "set of integers", we might have methods to sum the elements of a given set, to take the union of two sets, or to return a boolean indicating whether or not the set is empty.

In some situations, classes are referred to as "abstract data types", meaning that they encapsulate, or restrict access to objects of the class so that only the methods defined for the class can modify objects of the class directly. This restriction assures that the objects of the class cannot be changed in ways that were not anticipated by the designer of the class. Encapsulation is regarded as one of the key tools for reliable software development.  

Class Hierarchies

It is possible to declare one class C to be a subclass of another class D. If so, then class C inherits all the properties of class D, including the type of D and any functions defined for class D. However, C may also have extra properties. For instance, new methods may be defined for objects of class C, and these methods may be either in addition to or in place of methods of D. It may even be possible to extend the type of D in certain ways. Particularly, if the type of D is a record-structure type, then we can add new fields to this type that are present only in objects of type C.

Example : Consider a class of bank account objects. We might explain the type for this class informally as:

CLASS Account = {accountNo: integer;
                               balance: real;
                               owner: REF Customer;
                             }

That is, the type for the Account class is a record structure with three fields: an integer account number, a real-number balance, and an owner that is a reference to an object of class Customer (another class that we'd need for a banking database, but whose type we have not introduced here).

We could also define some methods for the class. For instance, we might have a method

deposit(a:  Account,  m:  real)

that increases the balance for Account object a by amount m.

Finally, we might wish to have various subclasses of the Account subclass. For example, a time-deposit account could have an additional field dueDate, the date at which the account balance may be withdrawn by the owner. There might also be an extra method for the subclass TimeDeposit

penalty(a:  TimeDeposit)

that takes an account a belonging to the subclass TimeDeposit and calculates the penalty for early withdrawal, as a function of the dueDate field in object a and the current date; the latter would be obtainable from the system on which the method is run.



Tags