Defining Classes and Creating Objects

Sather - A Language Tutorial
Prev | Chapter 2. Classes and Objects | Next

# 2.2. Defining Classes and Creating Objects

Objects are usually models of conceptual or real-world entities; they consist of a combination of data, which models the state of the entity and operations which model the behavior of the entity. The body of a Sather class consists of a list of features which define the data and behavior of the class. A class defines a new type and may be used to create object instances of that type.[1]

> [1] This is only true for reference, immutable and some kinds of external classes. Abstract a, partial and most external classes cannot have instances.

We will start by describing the data elements and then move on to the operations. In subsequent sections, we will describe the definition of object behavior in the form of routines. We will then point out that Sather provides a level of abstraction, which permits the state and behavior of the object to be treated in a uniform manner. Finally, we will describe the somewhat unusual meaning of assignment in Sather that makes this uniformity possible.

## 2.2.1. Defining Simple Classes

The state of a class is defined by attributes, which are have the prefix `attr`:

    class POINT is
       attr x:INT;
       attr y:INT;
    end;

The `POINT` class above defines an `'x'` and a `'y'` attribute both of which are integers. This class is useless, as it stands, since it provides no way to create instances of itself.

## Object Creation: `create` and `new`

To make objects of the `POINT` class, we have to introduce a `create` routine

    class POINT is
       attr x, y:INT;

       create(xvalue,yvalue:INT):POINT is
          res:POINT := new;
          res.x := xvalue;
          res.y := yvalue;
          return res;
       end;
    end;

The `create` routine first calls the special expression `'new'`. `'new'` creates a new uninitialized instance of the `POINT` class and returns it. All the attributes in the new instance have default 'void' values. It then assigns the `'x'` and `'y'` attributes of this new instance to `xvalue` and `yvalue` respectively. Instances of the `POINT` class can then be created as shown below

    p:POINT := POINT::create(3,5);

Since creation is such a common operation, Sather provides a special shorthand for calls to the routine `'create'`. The `'create'` routine shown could be invoked with the # sign as shown below

    point:POINT := #POINT(3,5);

Expressions using the `#` sign are referred to as creation expressions, and are a convenient shorthand used for creating new objects and initializing their attributes.

## Attribute access

When an object of the class `POINT` is created, the `'x'` and `'y'` attributes may be accessed by 'dotting' into the object.

    a:POINT := #POINT(3,5);
    -- Create a new point
    #OUT + a.x ;
    -- Prints out the value of 'x', which is 3
    a.x := 5;
    -- Sets the value of the 'x' attribute to 5

## Points to note

- The semantics of a class is independent of the textual order of its class elements. In particular, the actual attribute layout used by a Sather implementation is invisible to a programmer.

- The scope of feature names is the class body

- Feature names may be either lower or upper case.

- Class names must be all upper case letters (underscores and digits are permitted except as the first character).

- The feature namespace is separate from the class namespace.

- The scope of class names is the entire program; no two classes can have the same name (unless they have different number of parameters, which will be explained in the chapter on class parametrization).

- You have to explicitly call `'new'` in the create routine. The following code exhibits a common error:

      class POINT is
         attr x,y:INT;

         create(xval, yval:INT):POINT is
            x := xval;
            -- Run time error! We have no object as yet!
            y := yval;
         end;
      end;

## 2.2.2. Checking whether an object has been created

Before a variable is assigned to an object, the variable has the void value. The expression `'void'` may be used to determine whether a value is void or not.

The following example will print out the string "a is void!" since a `POINT` is a reference class and `'a'` has not been created.

    a:POINT;

    if void(a) then
       #OUT + "a is void!";
    end;

In the second version, the string "a is not void!" will be printed since an object has been assigned to the variable `'a'`:

    a:POINT := #POINT(3,5);

    if void(a) then
       #OUT + "a is void!"
    else
       #OUT + "a is not void!"
    end;

Note that the above test will not work in the same way for some of the built-in classes such as integers and booleans[2].

> [2] The void test returns true for all integers with a value of 0 and booleans with a value of false. In general, the void test is not useful for immutable classes.

## 2.2.3. Types Introduced

Each Sather variable and object has an associated type. The type of the object indicates the class that was used to create the object. In the following example, both '`a`' and '`b`' have the type `POINT`, indicating that they are associated with instances of the `POINT` class.

    a:POINT := #POINT(2,3);
    b:POINT := #POINT(4,5);

In this example, the type of the variable `'a'` is the same as the type of the object to which it is assigned. This is always the case with the reference classes we have seen so far.

When we introduce abstract classes (unnamedlink), we will see that some Sather variables can hold objects of many different types. In this case, it is useful to distinguish between the type of the variable (called the declared type) and the type of the object that it holds (called the actual type or the concrete type).

## 2.2.4. Hiding features: private and readonly

A fundamental feature of object oriented programming languages is that they permit an object to hide certain features which are for internal use only. Attributes may be completely hidden by marking them `private`. Routines may likewise be marked private, meaning that they cannot be accessed outside the original class. Attributes can also be hidden so that they can be read but not modified from outside the class, by marking them `readonly`.

    class POINT2 is
       private attr x:INT;
       -- x cannot be seen from outside
       readonly attr y:INT;
       -- y cannot be changed from outside
       create(xvalue,yvalue:INT):POINT is
          res:POINT := new;
          res.x := xvalue;
          res.y := yvalue;
          return res
       end;
    end;

This restricts external access to the attributes in the object

    foo is
       -- some other piece of code
       a:POINT2 := #POINT2(3,5);     -- Create a new POINT2
       #OUT + a.y;                   -- Print out '5'
       -- Illegal: #OUT + a.x;
       -- Illegal: a.y := 10;
    end;

## Points to note

- Privacy is on a per-class basis, rather than on a per-object basis. Thus, an object can access the private features of other objects of the same class. We actually use this fact in the `create` routine of the class `POINT2` above. Assignments to the attributes of `res` are being done outside the object being returned.

Prev | Home | Next
Classes and Objects | Up | Class Data: shared and const