Perfect Developer basic tutorial 4 This page last modified 2011-10-30 (JAC)

Simple class structure

Classes in Perfect are divided into a number of sections. The most common sections are the abstract and interface sections - indeed, many classes have only these sections.

Here is an example of a simple class, complete with a constructor:

class Book ^=
abstract
  var title: string,
      authors: set of string;
interface
  build{!title: string, !authors: set of string};
end;

This declares a new class called Book having attributes (i.e. data) title and authors. A book has a single title but may have several authors. We choose to represent the collection of authors as a set rather than a sequence or bag, on the assumption that the authors are distinct and it doesn't matter what order they are listed in.

The class also has a single constructor, which is the declaration that starts with the keyword build. This constructor takes a parameter of type string and another parameter of type set of string. By giving each parameter the same name as one of the attributes and preceding it with an exclamation mark, we indicate that the attribute is to be initialized directly from the corresponding parameter.

We can create a Book by using a constructor call expression like this:

... Book{"Life, the Universe and Everything", set of string{"Douglas Adams"}} ...

For example, we could add the following declaration, outside the class declaration:

const myFavoriteBook ^= Book{"Life, the Universe and Everything", set of string{"Douglas Adams"}};

As it stands, this class isn't very useful. We can create books, but we have to provide a list of authors each time, even though most books have only one author. After creating a book, we can't do anything with it except test it for equality with another book - we can't even access its title and authors, because they are private variables.

switched-on lampBy the way, two objects are equal in Perfect if each attribute (i.e. abstract variable) of one is equal to the corresponding attribute of the other.

Let's add another constructor that allows us pass just one author parameter, instead of a set:

class Book ^=
abstract
  var title: string,
      authors: set of string;
interface
  build{!title: string, !authors: set of string};

  build{!title: string, author: string}
    post authors! = set of string{author};


end;

This second constructor means we can declare:

const myFavoriteBook ^= Book{"Life, the Universe and Everything", "Douglas Adams"};

as well as the longer version. Note that the author parameter in the new constructor declaration is not preceded by an exclamation mark, because there is no variable named author to be initialized from the parameter. The post keyword introduces a postcondition. We will cover postconditions in more detail later on, but for now all you need to know is that
   post v! = e
states that the attribute v (and nothing else) changes such that its final value is equal to e.

Let's now deal with accessing the title and author of a Book.

First, we'll provide a way of extracting the title of a book. The usual way of doing this sort of thing in object-oriented languages is to provide an accessor function (perhaps called getTitle), which we can do in Perfect like this:

class Book ^=
abstract
  var title: string,
      authors: set of string;
interface

  function getTitle: string
    ^= title;


  build{!title: string, !authors: set of string};
 
  build{!title: string, author: string}
    post authors! = set of string{author};
end;

but in Perfect, a simpler way is to redeclare title as an interface function like this:

class Book ^=
abstract
  var title: string,
      authors: set of string;
interface
  function title;

  build{!title: string, !authors: set of string};
 
  build{!title: string, author: string}
    post b! = set of string{author};
end;

This means that given an entity b of type Book, the expression b.title yields the value of the title variable in b.

Redeclaring a variable as an interface function provides read-only access to it, just like an accessor function. It is also possible to redeclare a variable as an interface selector so as to provide read-write access to it, but this is rarely a good idea.


Next:  More functions

 

Save My Place Glossary Language Reference Manual
Tutorials Overview Main site   
Copyright © 1997-2012 Escher Technologies Limited. All rights reserved. Information is subject to change without notice.