Language Reference/Basic Concepts/Object System

From wiki.visual-prolog.com

External View

The description in this section is not supposed to be an introduction to classes; it is intended as a clarification of the class notions in Visual Prolog. The reader is expected to be familiar with common class notions. The description is purely conceptual in the sense that it does not refer to any syntax, implementation, etc. Moreover, this description does not consider any operational or programmatic aspects. While the reasons for introducing classes, objects, etc are mostly of programmatic nature, we find it valuable to describe the underlying concepts without reference to these programmatic reasons.

The class concept of Visual Prolog is based on the following three semantic entities:

  • objects
  • interfaces
  • classes
Object

An object is set of named object member predicates and a set of supported interfaces. Objects actually also have a state, but this state can only be changed and observed through the member predicates. We say that the state is encapsulated in the object.

Here encapsulation means the ability of an object to hide its internal data and methods, making only the intended parts of the object programmatically accessible. The importance of encapsulation and modularity is well known. Encapsulation helps building more structured and readable programs, because objects are treated like black boxes. Look at a complex problem, find a part, which you can declare and describe. Encapsulate it into an object, construct an interface and continue so, until you have declared all the sub-problems. When you have encapsulated the objects of the problem, and ensured, that they work correctly, you can abstract from them.

Interface

An interface is an object type. It has a name and defines a set of named object predicates.

Interfaces are structured in a supports hierarchy (the structure is a semi-lattice rooted in the interface object). If an object has a type denoted by an interface, then it also has the type of any supported interfaces. Therefore, the supports hierarchy is also a type hierarchy. An interface is a subtype of all its supported interfaces. We also say that the object supports the interface. If the interface is named X, then we say that the object is an X, or an X object.

Class

A class is a named object factory; it can create objects corresponding to a certain interface. Any object is created by a class, if an object was created by the class, which uses the interface C to construct objects then we call it a "C object".

All objects that are constructed by a certain class share the same definition of the object member predicates, but each object has its own state. Thus, the object member predicates is actually part of the class, whereas the state of the object is part of the object itself.

A class also contains another set of named predicates and an encapsulated state, known as the class members and class state, respectively. The class members and the class state exist on a per class basis, whereas the object members and object state exist on a per object basis. The class state can be accessed both by class members and by object members.

Notice! The set of object member predicates that a class defines is the union of the predicates declared (transitively) in the interfaces of that class. More specifically this means that, if the same predicate is declared in two different interfaces then the class will only provide one definition of that predicate. So the class only sounds if that makes sense, i.e. if the intended semantics of these two inherited predicates are the same.

Notice that interface support must be specified explicitly. The fact that some class provides the predicates corresponding to some interface does not imply that the class supports the interface.

Module

In fact a class need not be able to manufacture objects at all. Such class may have only class members and the class state. And therefore, such class can be considered to be a module rather than a class.

Identity

Every object is unique: objects have a changeable state and since the state of the objects can be observed by means of their member predicates an object is only identical to itself. I.e. even if the states of two objects are identical, the objects are not identical, because we can change the state of one object without changing the state of the other object.

We never have direct access to an object state, we always access an object state by means of a reference to the object and while an object is only identical to itself, we can have many references to the same object. Thus, the same object can be accessed through many different references.

Classes and interfaces are also unique; they are identified by their names. Two interfaces or classes cannot have the same name in the same program. A class and an interface can only have the same name if the class constructs objects of that interface.

The essence is that structural equality does not imply identity for objects, classes nor interfaces.

Internal View

Where the previous section described objects, classes, and interfaces in terms of their external behavior, this section will extend this description with internal issues. These internal issues have more programmatically nature; they are concerned with splitting of classes onto the declaration part and the implementation part.

From a programmatic point of view, classes are the central item: the code is contained in the classes.

Interfaces mainly have static importance. In fact, interfaces only exist in the textual representation of a program; there is no (direct) runtime representation of an interface.

Objects, on the other hand, have mainly dynamic importance. Objects are not directly visible in the program; they do not exist until the program actually runs.

A class consists of a declaration and an implementation. The declaration declares the public accessible parts of the class and the objects it generates. The implementation on the other hand defines the entities declared in the class declaration. The basic implementation of predicates is of course clauses, but predicates can also be defined by means of inheritance, or resolved to external libraries.

A class declaration in Visual Prolog is purely declarative. It only states which entities you can access: not how or where they are implemented.

A class implementation can declare and define further entities (i.e. domains, predicates, etc), which are only visible inside the class itself. I.e. they are private.

The state of an object is stored in the object as its facts. These facts are declared as normal facts (database) sections in the implementation of the class. Facts are local to each object (like other object entities), whereas class facts are shared among all objects of the class.

Facts can only be declared in the implementation of a class and, therefore, cannot be accessed (directly) from outside the class.

The implementation of a class can also declare that it supports more interfaces than mentioned in the declaration. This information is, however, only visible in the implementation itself and is, therefore, private.

Code Inheritance

In Visual Prolog code inheritance only takes place in the implementation of a class. Visual Prolog has multiple inheritance. You inherit from a class by mentioning the class in a special inherits section of the implementation. The classes you inherit from are called parent classes or super-classes. Child-class or sub-class is the dual to parent class, we also say that the child classes inherit from the parent classes. A child class can only access its parent classes through its public interface, i.e. it does not receive any extra privileges than anybody else that use the parent class.