Strict separation of interfaces and implementations

According to the black-box principle, a Lava class consists of two completely separated parts (that may even reside in different Lava files):

The class interface (or short: class) contains the exported features (member variables/attributes and member functions/methods) of the class that can be referenced from anywhere (unless they are protected). Class interfaces support multiple inheritance (with shared base classes), i.e., a class may be derived from several other base classes.

The implementation contains the "private" features of the class (which cannot be referenced from the "outside world") and the implementations of all non-abstract functions that are explicitly enumerated in the class interface.

Methods/Member functions that are inherited from base classes and that are not overridden in the current class have to be implemented in the implementations of those base classes and need not be re-implemented in the implementation in question. In this (and only this) sense implementations are inherited (or better: taken over) from base classes in Lava, quite in contrast to the semantics of the "implements" clauses in Java classes, which force you to implement all functions (including the inherited base class functions) in the class containing the "implements" clause. (See also object creation below.)

Older, non-object-oriented languages like Modula-2 and Ada, that were based on "abstract data types", had already achieved a clean syntactic separation of "interfaces/definitions" and "implementations" according to the important "principle of information hiding". The same class could be implemented in several alternative ways, and an implementation could be changed without affecting the users of the class, particularly without any need to recompile the dependent program modules.

Strict separation of interfaces and implementations as well as the distinction between state and value objects is downright a necessity if you aim at a language that is from the beginning on not only object- but also component-oriented, where components are pre-fabricated, dynamically loadable software modules written in any language, that communicate with other components via standardized function-call interfaces, like CORBA or COM components.

In object-oriented languages this very useful and reasonable separation has been abandoned again so far. The distinction between public, private, and protected members of a class is an insufficient substitute for such a strict syntactic separation.

The distinction made by Java between "interfaces" and "classes" doesn't meet the requirements as well:

  1. A Java interface is a collection of functions solely. You cannot specify member data in a Java interface. So you could speak of a Java interface as being a purely behavioral view of a class that implements the interface, whereas a Lava class interface is just the public (implementation-independent) part of a class.
  2. You need not use Java interfaces; you can completely ignore them and use classes instead, as in C++, to specify the public (interface) as well as the private (implementation) features of objects. A third possibility is to use "abstract classes" as a substitute for interfaces with data members. So there is no clear separation of the roles of interfaces and classes in Java.

One reason for the dual nature of classes in Java is that you need classes in Java not only for describing implementations but also for specifying "interfaces with data members". The reason, in turn, for the absence of data members in Java interfaces is the Java compromise as to multiple inheritance: Java interfaces support multiple inheritance, Java classes don't, since a general support of multiple inheritance for classes (including data members) would have been considerably more expensive.

Some people have made a merit of this deficiency by saying that you should not expose data members in interfaces anyway. They recommend that you should declare variables in Java always as being of some interface (rather than class) type and use classes solely for describing the implementations of interfaces. But if you strictly separate (public) interfaces and (private) implementations and if, as a consequence, interfaces are the only way of exposing the public features of data types then it would be extremely strange and unnatural in many cases to hide their data members behind Set/Get... or other access functions. For services this might be acceptable frequently, although it may be more natural even then to expose, e.g., the current balance of a bank account as a read-only data member of an account interface. But for value objects, which expressly serve as messages between services and which are primarily characterized by their data structure, it would certainly be unacceptable to hide their data members behind access functions.

Notwithstanding, access to a data member xy of a Lava class may be implemented by proper Set and Get functions that are invoked implicitly on read and assignment access to this data member. In a Lava class you can specify this as an optional property of a data member, but the corresponding Set/Get functions will appear only in the implementation of the class.

Unlike Java classes, a Lava implementation implements exactly one class (and thus has the same name as the class). Lava implementations serve only for implementing their corresponding classes, and they do not inherit from other implementations.

Meaning of "implements": If class B extends classes A1, ..., An then an implementation of B provides implementations of those non-abstract member functions of B that are listed explicitly in the declaration of B, i.e., that override member functions of A1, ..., An or that have been declared for the first time in B. So an implementation of B does not comprise implementations of A1, ..., An but concerns only the new or overridden functions of B.

Object creation

A class A may be marked as being "creatable". Then it may be used in "new" operations to specify the type of the objects to be created. It is the job of the Lava run time system to find an implementation of A, as well as implementations of all direct or indirect base classes of A. The ("public") features (member variables and member functions) of all those classes and the ("private") features of all those implementations are combined and make up the implementation of the new object of type A.

The search process for an implementation corresponding to a given class A proceeds as follows: At first the Lava interpreter searches the current file containing the "new" expression. If an implementation of A isn't found there then all directly or indirectly included files are searched in the same way for an implementation.

Note that the "local" features of an implementation, that are declared only within this implementation and that are not exported through the corresponding class interface, cannot be referenced from anywhere outside this implementation. In particular, an implementation cannot use local features of other implementations that are "ingredients" of the same object: Implementations may only reference their own (private) features and features that are exported through class interfaces. (The latter features may be declared protected, however, which means that they may be referenced only by implementations of classes that extend the class containing the protected feature.)

Interfaces in Lava

Because of this close relation between implementations and the class interfaces that they implement we use the term "class" in Lava just as a synonym for "class interface".Cf. the section "How Lava locates implementations of classes" to understand how different implementations may be associated with the same class.

The Java notions of "interface", "class", "implements" and "extends" provide two unrelated inheritance structures: one for interfaces and one for classes. You can use classes as well as interfaces to declare the types of variables, and a Java class may implement any number of interfaces. We believe that all this is more confusing as helpful for programmers. In contrast to this, Lava provides an inheritance notion only for class interfaces (= classes), types of Lava variables can be declared only with classes, and a Lava implementation implements exactly one class interface and doesn't serve any other purpose.

Shared base classes

Lava supports multiple inheritance with shared base classes, where "shared base class" is used in the sense of the "virtual base classes" of C++: If a Lava class A inherits the same base class B several times on several inheritance paths then an object of type A contains only one base object of type B.

Note that "virtual base class" means something different in Lava than in C++: Lava allows you to specify a virtual type as a base class of a new class, and these are called "virtual base classes". Cf. our virtual base samples. Lava virtual base classes provide one particular way to implement mixins in Lava (see below).

Mixins, multiple inheritance, virtual base classes

Often you would like to enhance some basic class with flexibly selectable supplementary feature sets. Usually such a supplementary feature set wouldn't represent a class of objects that may be created independently but it rather resembles a garnishment that you may select for your meal in better restaurants: they are not meals of their own but just supplements.

In the programming context such supplements are called mixins. (Cf. the discussion (in German) of mixins in DseWiki.) Lava provides essentially two different ways to realize mixins:

  1. By multiple inheritance, where the enhanced class inherits from some basic primary class and from selectable supplementary classes that often will be non-creatable since it doesn't make sense to create objects from them.
  2. By virtual base classes (see above). This resembles the way how mixins may be implemented in C++ (apart from multiple inheritance as in Lava): In C++ you can declare template classes in a way that their base class(es) are template parameters.

See also

"Private / protected / friend" counterparts in Lava

Two object categories

Stages in the life of Lava objects

Component objects