Go to the first, previous, next, last section, table of contents.

7 Class Specifications

A main feature of Larch/C++, the feature that supports object-oriented programming, is the ability to specify C++ classes. The syntax is as follows. The syntax of a class-specifier is much the same as C++. In addition, the member-seq (see section 7.2 Class Member Specifications) besides containing declarations and specifications of data and function members, may contain one or more of the following: uses-clauses (see section 9.2 The Uses Clause), invariant-clauses (see section 7.3 Class Invariants), and constraint-clauses (see section 7.4 History Constraints). The member-seq may also contain various features to support the specification of behavioral subtypes and specification inheritance (see section 7.9 Inheritance of Specifications and Subtyping).

class-specifier ::= class-head { [ member-seq ] }
class-head ::= class-key [ identifier ] [ base-spec ]
        | class-key nested-name-specifier identifier [ base-spec ]
        | class-key [ nested-name-specifier ] template-class-instance [ base-spec ]
        | abstract class [ nested-name-specifier ] [ identifier ] [ base-spec ]

A class-head is part of the C++ interface of the specified class.

The syntax of a class-specifier is also used in Larch/C++ for the declaration of signature types; these are used to help specify the requirements on template parameters (see section 8 Template Specifications). It is also used for defining struct and union types (see section 5.2.3 Type Specifiers). Such types are declared by using a class-key of struct or union.

In Larch/C++, structure, class, union, and signature types are treated in the same manner. (Of course, as in C++, the visibility of a structure starts out as public, whereas for a class it starts as private.) For such types, Larch/C++ can automatically construct a model of their abstract values for you, by putting together the declared non-static class members (which would usually be specification-only declarations for classes). This is the usual and common way to specify such types. However, you may also assume complete responsibility for providing the abstract model by using a trait that specifies a sort of the same name as the type you are defining (and the trait function contained_objects). (See section 9.2 The Uses Clause for how to use a trait. Examples are also given later in this chapter.) If you use such a trait, that overrides the automatically-supplied abstract values. See section 11.10 Structure and Class Types for details on the automatically-supplied traits for struct types. See section 11.11 Union Types for details on the automatically-supplied traits for union types.

In the rest of this chapter, we will use the word "class" instead of constantly saying "class or structure or union." However, aside from the difference in default visibility noted earlier, everything said about classes applies equally to structures and unions.

Returning to the specification of classes, in the member-seq, the uses-clause allows one to describe traits that are used within a class specification. As in our examples, however, when one uses a trait to aid a class specification, most often the uses-clause would appear outside the class, so that clients will also have that trait available when they include the class's specification. See section 9.2 The Uses Clause for details.

A C++ class satisfies a class specification if it has the same interface (see section 2.2 Interfaces), if it has the declared data members, and if each member function satisfies its specification.

The main focus of the sections below is on how to use class specifications, and how the various features interact with each other.

Go to the first, previous, next, last section, table of contents.