Component Relations
Assume that component c1 instantiates two components: c2 and c3. Moreover, assume that the name of the c2 instance is i2 and the name of the c3 instance is i3.
In this scenario, c1 is the parent of i2 and i3. i2 and i3 are children of c1. Finally i2 and i3 are sibling.
Component Communication
In Parham two component instances can communicate in three ways.
As a sample, recall the Tree component discussed in the previous lesson.
Tree[Root, Node]
void Root.insert (Node);
extern int Node.compare (Node);
When a component uses Tree, it can call insert to add an item to Tree. This is a down call. Moreover, it has to provide an implementation for Node.compare. For example, in the previous lesson it was used to store a set of persons.
Tree[People, Person];
int Person.compare (Person p) {…}
Now, when Tree calls Node.compare, Person.compare is actually called. This is a sample of up call.
Of course, extern methods can be used to make sibling calls.
This is discussed through an example in this lesson.
Sibling Component Interactions
Like the example of the previous, a Tree is used to store a set of Persons.
However, in this implementation Person is implemented as a separate component.
Person component
The Person component implements Person. It has just one class, This, which represents a Person. It defines the attributes of This (a person), a constructor and three methods for it.
App component
App is the main component of the application. It has two internal classes: People and CPerson. People is the class that represents a group of persons and CPerson represents a person.
App declares three instances: an instance of Person and two instances of Tree. The Person component adds the properties of a person (introduced by the Person component) to the CPerson class.
The Tree components store CPerson objects in different orders. The first one orders them based on their name and the second one stores them based on their age.
This is the declaration of the first Tree component.
Tree[People ageSorted, CPerson]
{
Node.compare = Person.This.compareByAge;
Node.process = Person.This.print;
}
Remember that Tree has two extern methods: compare and process. Now, this declaration says that the compare of Tree is mapped the on compareByAge method of This class of the Person component. Moreover, it shows that the process method of the Node class of Tree is mapped on the print method of the This class of the Person component.
Doing so effectively provides a way that two sibling component instances interact with each other.
After the instance declarations, the component defines a constructor for the CPerson class. Note that it calls the constructor of the This class of the Person component.
The rest of the App component is straightforward.
The complete code of the sample can be downloaded from the link provided in the beginning of the code.
Person[This]
This
{
char[] name;
int age;
}
This (char [] _name, int _age)
{
name = _name;
age = _age;
}
int This.compareByAge (This p)
{
return age – p.age;
}
int This.compareByName (This p)
{
return cstrcmp (name, p.name);
}
void This.print ()
{
cprint2 (name, age);
}
Person component
App
People[];
CPerson[];
Person[CPerson];
Tree[People ageSorted, CPerson]
{
Node.compare = Person.This.compareByAge;
Node.process = Person.This.print;
}
Tree[People nameSorted, CPerson]
{
Node.compare = Person.This.compareByName;
Node.process = Person.This.print;
}
CPerson (char [] _name, int _age)
: Person.This (_name, _age) {}
void People.insert (CPerson p)
{
ageSorted.insert (p);
nameSorted.insert (p);
}
void People.print ()
{
cprint1 (“Sort by age:n”);
ageSorted.process ();
cprint1 (“nSort by name:n”);
nameSorted.process ();
}