| « Three steps to understand the main idea of the concept-oriented programming (COP) | FAQ on the concept-oriented programming (COP) updated » |
One of the main concerns in the concept-oriented paradigm is representation and access (RA). Its importance is a consequence of another concept-oriented principle which says that a great deal of any complex system functionality is executed behind the scenes during object access. This hidden functionality is associated with references or other types of identifiers (as opposed to objects). In the concept-oriented programming (COP) the system functionality is divided on two types: (i) conventional business methods (BMs), and (ii) intermediate representation and access (RA) methods. An amazing feature of the concept-oriented programming is that it allows us to describe both sides of any system simultaneously. And the main solution consists in using a new programming construct called concept.
Concept consists of two parts: an object class and a reference class. Instances of the object class, called objects, are passed by reference. Instances of the reference class, called references, are passed by value. Thus we get two worlds which co-exist in any system: the world of objects and the world of references. Currently, there are a lot of methods for modelling objects and their functions. However, there are no methods for modelling references. Indeed, what if I want to define my own format for identifying objects in my program? I need to invent some special tricks or use non-standard patterns because no general solution currently exists. And it is precisely where we can use concepts with their reference classes which are intended to describe the format of references and their functions.
For example, if my objects need to be represented by integers then I define this field in the reference class:
concept Indirect
class {
static Map map.create();
}
reference {
int id; // Object identifier
}
After that I add a special method for resolving this reference:
concept Indirect
class {
static Map map.create();
}
reference {
int id; // Object identifiers
void continue() { // Continuation method
System.out.println("> Begin resolution");
Object o = context.map.get(id); // Resolve reference
o.continue(); // Invoke target method
System.out.println("> End resolution");
}
}
Finally, any target class can be included into this concept using keyword 'in' and all its instances will be automatically represented by integers:
class Customer in Indirect { ... }
class Product in Indirect { ... }
class Source {
void myMethod(Customer c, Product p) {
...
String name = customer.getName();
...
double price = product.getPrice ();
...
}
}
Here two parameters to myMethod are indirect references defined in concept Indirect. More specifically, they are integers because concept Indirect is a parent of classes Customer and Product. For example, if a method of the target class will be called then the compiler will automatically wrap it in the appropriate intermediate method of the parent concept. This method when called will generate the following output:
$ > Begin resolution $ *** Here Customer::getName() is called $ > End resolution $ > Begin resolution $ *** Here Product::getPrice() is called $ > End resolution
An advantage of this approach is that objects and methods are used as usual, i.e., it retains the illusion of instant access independent of how objects are represented and access. This method guarantees that the intermediate procedures will always be executed and hence the logic of RA is ensured. It allows us to define nested indirection where a reference substitutes for another reference and so on till the system format of references. And it is possible to define hierarchical references consisting of several segments like a postal address. Objects in this case can reside anywhere in the world but we can still use them as usual. Thus programming in this paradigm is aimed at modelling references and their functions rather than only objects.