The addressable aspect in the previous section was an example of a general aspect with both data-items and methods.
The following example illustrates aspects that only have methods. In other languages this kind of aspects are defined by a special interface definition, but we will define also these kinds of aspects by means of classes. Usually interface only have method signatures, i.e. name, parameters and return type, while aspects used for interface may have methods with more than signatures.
We start out by the simple aspect of being printable:
class printable:
print:<
inner(print)
Different classes of objects may have a printable
aspect. Here we define that Person
objects are printable:
class Person(name: var String):
asPrintable: obj Printable
print::
name.print
Because the description of asPrintable
is nested within Person
, the data item name
of Person
is visible, and it is therefore possible to extend print to print the name
.
A Person
object are printed like this:
JohnSmith: ref Person
JohnSmith := Person("John Smith")
...
JohnSmith.asPrintable.print
This will not surprisingly print “John Smith”. A more interesting example is the case where we have a set of Person
objects and apply asPrintable.print
to all of objects in this set:
persons: obj Set(Person)
-- insert Person objects in this set, e.g.:
persons.insert(Person("John Smith"))
persons.insert(Person("Liza Jones"))
persons.insert(Person("Mary Pole"))
...
persons.scan
current.asPrintable.print
The same effect could have been obtained by defining Person
as a subclass of Printable
, but that would classify Person
to be Printable
, and that is not what we want to express. Subclassing works well for classification, but for aspects we typically would like to have that a class like Person
can have more than one aspect.
Suppose we also have the notion of being movable:
class Movable:
move(newAddr: ref Address):
inner(move)
then Person
could also be movable:
class Address:
-"-
print:<
-"-
class Person(name: var String):
addr: obj Address
asPrintable: obj Printable
print::
name.print
address.print
asMovable: obj Movable
move::
addr.change(newAddr)
With the above class definitions, the properties of Printable
(in this case just the method print
) is also a property of Person
, although via the name asPrintable
. Correspondingly for move
of Movable
:
Joe: ref Person
...
Joe := Person("Joe")
Joe.asPrintable.print
Joe.asMovable.move(Address("Norway","Oslo","Røahagan", 33))
As mentioned, the above aspects, Printable
and Movable
, are example of interfaces in other languages, with only methods. As the methods print
and move
are defined independently of Person
(or other classes that should be Printable
and Movable
, interfaces usually do not have any statements describing their actions. This is not the case for aspects that work as interfaces.