Instance Declaration

Component instance declaration is the main reusability mechanism of Parham. When a component needs the service of another component it declares an instance of that component.

For example, consider the Queue component (discussed in the previous lesson) whose prototype is as follows.

Queue[Root, Node]

Now, consider the following declaration.

Queue[People, Person];

By  this declaration, a copy of Queue.Root role is added to the People class and a copy of Queue.Node role is added to the Node class.

Named/Unnamed Roles

When an instance is declared it is possible to assign a name to the roles or leave them unnamed. Having the Queue component, both of the following declarations are valid.

Queue[People, Person];

Queue[People p, Person];

In the first declaration, class People inherits from class Root of Queue and in the second declaration, it has an attribute whose type is People and whose name is p.

Composition

In addition, note that component instantiation is implemented by composition. It means that if two instances of a component are defined on a class, the class has two copies of that role.

For example, assume that the following declarations are done.

Queue[People, Person];

Queue[People, Person];

Now, People has two copies of Root of Queue and Person has two copies of Node of Queue. Of course, as they are unnamed it is not possible to access them. In fact, to access them, at least one of them should be named.

Extern Properties

The extern properties of a component should be resolved when it is instantiated. Usually the extern properties are resolved by name matching. For example, consider the Tree component discussed previously.

Tree[Root, Node]

It has an extern method whose declaration is as follows.

extern int Node.compare (Node);

Now, assume that an instance of Tree is declared as follows.

Tree[People, Person];

Assume that Person has a compare method whose prototype is as follows.

int Person.compare (Person);

Now, the compare method of Tree.Node is resolved to be the above method.

Of course, this is not the only way to resolve an extern property. Another way to resolve an extern property is to explicitly specify it. This is called a delegate.

This is an example of a delegate.

Tree[People, Person]                                 

{                                                                      

Node.compare = compareByName

}                                                                     

Of course, compareByName should belong to the Person class and its prototype should be as follows.

int Person.compareByName (Person);

Assume that you have a set of persons and you need to lookup a Person by his/her name or age.

To efficiently lookup a Person one way is to use a binary search tree (the Tree component).

Therefore, we need two binary trees: one of them stores the Person objects ordered by their name and the other one stores them ordered by their age.

It yields the code shown in the front panel.

Moreover, the complete code of the sample can be downloaded from the link given above.

App


People[];

Person[];


Tree[People ageSorted, Person]

{

    Node.compare = compareByAge;

}

Tree[People nameSorted, Person]

{

    Node.compare = compareByName;

}


Person

{

    char[] name;

    int age;

}

Person (char [] _name, int _age)

{

    name = _name;

    age = _age;

}

int Person.compareByAge (Person p)

{

    return age – p.age;

}

int Person.compareByName (Person p)

{

    return cstrcmp (name, p.name);

}


void People.insert (Person p)

{

    ageSorted.insert (p);

    nameSorted.insert (p);

}