next up previous contents
Next: Constants Up: Shore Data Language Reference Previous: Name Scopes

 

Interfaces

    interface_dcl : 'interface' ID [ interface_body ]
    interface_body : [ inheritance ] '{' interface_dcls '}'
    inheritance : ':' parent ( ',' parent )*
    parent : access_spec scoped_name
    access_spec : 'private' | 'protected' | 'public'
    interface_dcls : ( access_spec ':' interface_members )*
    interface_members : interface_member*
    interface_member : const_dcl ';'
        | type_dcl ';'
        | attr_dcl ';'
        | relationship_dcl ';'
        | op_dcl ';'
        | override ';'
    override : 'override' scoped_name ( ',' scoped_name )*

An interface definition is similar to a class definition in C++. The access_specs preceding names of parent interfaces and introducing groups of member declarations have exactly the same meaning as in C++, except that they are not optional. The form "interface ID; (with no interface_body) denotes a "forward-declaration; the complete declaration of the interface must appear elsewhere in the same module.

A const_dcl defines a constant value. A type_dcl defines a type, which may be simple (integer, float, etc.) or structured. Types are described in more detail below. An attr_dcl introduces an attribute, which corresponds to an ``instance variable'' in SmallTalk or a ``data member'' in C++. The attributes of an object define its state. A relationship_dcl defines a special kind of attribute called a relationship, which establishes a correspondence between objects.

An op_dcl introduces an operation. Operations are similar to ``methods'' in SmallTalk or ``function members'' in C++. SDL defines only the signatures of operations. They are bound to executable code in a language-dependent manner. An override does not introduce a new member, but indicates that the named members (which must designate inherited operations) will be bound to code in this class that overrides the binding in ancestor classes. (A similar feature is in Modula 3. C++ requires that the entire function header be repeated, but that it exactly match the header in base class from which the function member is inherited. The proposed C++ standard relaxes the requirement for an exact match, allowing the return type of the overriding function to be derived from the return type of the function it is overriding. Introduction of a similar feature into SDL is for further study.)

Override applies only to operations; it is an error to name attributes or any members other than operations in an override.

 

Example

    interface AtomicPart {
    public: 
        attribute long               id; 
        attribute char               type[TypeSize]; 
        attribute long               buildDate; 
        attribute long               x, y; 
        attribute long               docId; 

        attribute set<Connection>    to;   // to connection objs
        attribute set<Connection>    from; // back pointers 

        attribute ref<CompositePart> partOf; // up pointer 

        void swapXY(); 
        void toggleDate(); 
        void DoNothing() const; 

        long traverse(in BenchmarkOp op, 
                inout PartIdSet visitedIds) const; 
        void init(in long ptId, in ref<CompositePart> cp); 
        void Delete(); 
    };

  An interface is a name space, as defined in the previous section. The complete set of names defined by an interface includes the names defined by the interface's members as well as names defined by its parents (if any). The complete set of definitions is formed by taking the set-theoretic union of sets of scoped names. Thus members with the same name introduced in different interfaces can be distinguished by their scoped names, and a given member inherited from the one ancestor by multiple paths contributes only one member to a derived interface. (In C++ terminology, this means that all inheritance is effectively ``virtual.'') Each name defined by a (member of an) interface hides definitions of that name inherited from its parents. A use of an unqualified name inside an interface refers to the definition of that name in the interface or one of its ancestors that hides all other definitions. If no definition hides all others, the name is ambiguous and must be qualified. (This corresponds to the so-called ``dominance rule'' of C++). If there is no definition of the name in the scope containing the use, the use identifies a definition in an enclosing scope (if any).

SDL does not support operator (method) overloading.

 

More Examples

    interface A { 
        public: 
            const long a = 1; 
            const long b = 2; 
    };

    interface B : public A { 
        public: 
            const long c = b; //  c = B::b = 3 
            const long b = 3; 
    }; 

    interface C : public A {
        public: 
            const long c = 4; 
    }; 

    interface D : public A, public C {
        public: 
            const long d = 5; 
            // D defines A::a, A::b, B::b, B::c, 
            //        C::c, and D::d 
            // Inside D, a, b, and d can be used without
            // qualification, but c must be qualified.  
            // The name b resolves to B::b, since its 
            // definition hides A::b, but neither B::c 
            // nor C::c hides the other. 
    };



next up previous contents
Next: Constants Up: Shore Data Language Reference Previous: Name Scopes



Marvin Solomon
Fri Aug 2 13:39:38 CDT 1996