The fact that a number objects from different classes may be addressable is represented by defining a class Address
:
class Address:
country: var String
town: var String
street: var String
streetNo: var Integer
print:
(country,town,street,streetNo).print -- muligt? men ikke pænt
change(c, t, s: var String, no: var integer):
...
Address
objects have the data items country
, town
, street
, and streetNo
. The address may be changed by the change
method, and it may be printed by the method print
.
Customer
objects with an address is represented by Customer
having an Address
object:
class Customer:
-"-
addr: obj Address
The fact that Customers
have an addr
object as above implies that the attributes of the Address
object are “kind of attributes of the Customer
as well”, however, they are only indirect attributes as they have to be accessed through addr
, like e.g.
aCustomer.addr.print
where aCustomer
is a reference to a Customer
object. The same would be the case inside the class Customer
:
class Customer: Person
-"-
addr: obj Address
...
addr.print
...
One could argue that for Address
to be an aspect of Customer
, the properties of Address
should be directly accessible and not via the name addr
of the part object. This would have been the case if Customer
had been a subclass of Address
, but that is obviously a wrong way to model this situation. A customer would typically be a type of e.g. person and it will have an address. From a modeling approach, a customer is not an address, but a customer has an address.
The addr
object is a simple means to represent an aspect like address, as we use an already known mechanism of an object data item (obj). However, it should be possible not only to apply a given aspect like Address
to any class of object, but also to tailor the aspect to the class to which it is applied.
The print
method of Address
simply prints the address. If we also would like to print the name of the costumer, then we can not define addr
simply as an Address
object.
The usual way of making the print
method so that it can be tailored in Address
aspects of different classes or objects is to define it as a virtual method:
class Address:
-:-
print:<
inner(print) -- whatever to print from the class/object that has
-- an Adress aspect
country.print -- foreløbig bare sådan, så det i det mindste fungerer
town.print
street.print
streetNo.print
Instead of representing an Address
aspect just as an Address
object, the aspect is then rather represented by a singular object with Address
as a superclass and with an extension of print
:
class Customer: Person
-"-
addr: obj Address
print::
name.print
Because print
is extended in the context of Customer
, i.e. nested in the description of Customer
, the name
data-item of Customer
is visible and can therefore be printed in the extension of print
.
Aspects may typically be applied to more than one class. Here it is applied to class Bank:
class Bank:
name: var String
addr: obj Address
print::
name.print
In this case print
will print the name of the bank.
Suppose that we have a class BankCustomer
that is subclass of Customer
:
class BankCustomer: Customer
bankName: var String -- the name of the bank
-- where the bank customer is a customer
Suppose that we still want to represent the Address
as an aspect of Customer
, and in addition of class BankCustomer
as a subclass of Customer
, but still so that the aspect is tailorable in both Customer
, in BankCustomer
, and in further subclasses of BankCustomer
. Then the above definition of addr
will not do; we vill then have to define the class of addr
by a virtual class AddrType
:
class Customer: Person
class AddrType:< Address
print::<
inner(print)
name.print
addr: obj AddrType
class BankCustomer: Customer
bankName: var String
class AddrType::<
print::<
inner(print)
bankName.print
Like the singular object addr
as a subclass of Address
is defined in the context of Customer
and therefore have access to the name
property. In this case the class AddrType
is also defined in the context of Customer
. Note that print
in AddrType
defined in Customer
is extended, but still virtual (::<
) so that it can be further extended in AddrType
defined in BankCustomer
.