• No results found

Assignment and assignment attempt

6 The Blue Language

6.6 Design by contract

6.9.1 Assignment and assignment attempt

The assignment is a multi-assignment and was discussed in section 6.5.3. An assignment attempt is written with a ?= symbol:

a ?= b

The assignment attempt uses the same symbol and the same semantics as Eiffel [Meyer 1992, p 330]. It is used to attempt an assignment from a superclass variable to a subclass variable. Consider:

class A is

== This is the superclass ... end class and class B is A == B inherits from A ... end class

If we have variable declarations:

var

a : A b : B then an assignment

CHAPTER 6: THE BLUE LANGUAGE

is legal because of the subtype relationship. (A subclass in Blue also establishes a subtype relationship. Subclassing and subtyping are inseparably linked Ð see section 6.13: Inheritance.) An assignment

b := a

on the other hand, is illegal because it is not type safe. The assignment attempt, however,

b ?= a

is legal. On execution the dynamic type of a is checked, and if it is of type B or one of its subtypes the assignment is executed. If its dynamic type does not conform to B, then nil is assigned.

We debated for a long time whether the assignment attempt should be a part of Blue. There were doubts about its usefulness and necessity in a language. One can argue that usually, when an assignment attempt is used, the program is badly designed. Improving the design can, in most cases, lead to the elimination of the assignment attempt from the code. Let us consider an example.

Assignment attempts are necessary when a programmer knows or suspects that an object is of a subtype of the statically known type, and needs to access operations of that subtype. This is the case if we use a polymorphic list. As an example here, we can use a list of animals in an environmental simulation. ÒAnimalÓ would be an abstract superclass of, say, the classes ÒSharkÓ, ÒSheepÓ and ÒLionÓ. The simulation would hold a list of animals, and once in every time interval it would go through the list to activate each particular animal to do whatever it is supposed to do. Let us assume that sharks swim, sheep eat and lions hunt.

In a na•ve implementation, we might need to ÒcastÓ the animal object back to its dynamic type in order to call the routine shark.swim, sheep.eat and lion.hunt. The following code fragment illustrates this technique:

animals.initScan

loop

anAnimal := animals.getNext

exit on anAnimal = nil -- end of list

aShark ?= anAnimal -- try shark

if aShark <> nil then aShark.swim

else

aSheep ?= anAnimal -- try sheep

if aSheep <> nil then aSheep.eat

else

aLion ?= anAnimal -- try lion

if aLion <> nil then aLion.hunt

end if end if end if end loop

CHAPTER 6: THE BLUE LANGUAGE

This is unfortunately the way in which the assignment attempt is mostly used by inexperienced programmers, and it is indeed bad design. This pattern is inelegant, unnecessarily complicated and a hindrance to system maintenance and extendability. It does not make use of one of object-orientationÕs most powerful features: dynamic dispatch. For this example, a better design would use an ÒactÓ routine in the abstract class ÒAnimalÓ (as a deferred routine), call the ÒactÓ routine for each animal in each time interval, and leave it up the animal itself to determine what kind of action it wishes to perform (swim, eat or hunt). Here is the modified code.

animals.initScan

loop

anAnimal := animals.getNext

exit on anAnimal = nil -- end of list

anAnimal.act

end loop

This code is clearly shorter, more elegant, and does not need to be changed when new animal subclasses are introduced to the system.

The argument so far suggests that we exclude the assignment attempt from the language. It is regularly misused and seems to invite bad design.

There are, however, valid uses of the assignment attempt. An example is found in the collection class library in the Blue system (a standard library that is part of the system distribution). Here we have an abstract class ÒListÓ with two subclasses, ÒLListÓ and ÒIndexListÓ. ÒLListÓ and ÒIndexListÓ are different implementations of the List type (a linked list implementation and an array implementation, respectively). Both share a common interface.

One of the routines in the List interface is ÒappendÓ. This routine joins two lists into one by appending one list to the other. The parameter to this routine is of type ÒListÓ. This means that not only two array lists or two linked lists may be merged, but also an array list can be appended to a linked list and vice versa.

In the implementation of this routine, the assignment attempt is used. This allows the code to distinguish between the two possible parameter types (linked list or array list) and to use different techniques to join the two lists. Using an assignment attempt could have been avoided by using the common interface operations to access the list elements separately. This, however, would have significantly affected performance of the operation. It would have resulted in the provision of a routine with exponential runtime behaviour in a standard collection library where a routine with constant execution time should have been available. This is not acceptable.

Note that we have previously argued that performance is not of paramount concern in our system. This, however, applies to constant performance degradation of student programs, not to bad programming. We can accept a system that executes programs, say, 20 times slower than a professional system, but we cannot accept a system that uses exponential algorithms where linear or even constant time algorithms should be used. The reason is that this (order of execution time) is something that we might want to teach to our students. It is important that our own libraries then make use of good algorithms.

CHAPTER 6: THE BLUE LANGUAGE

For the assignment attempt, this means two things:

· It is not used very frequently, and it can easily be misused. · There are some examples where its use is necessary.

The problem with excluding the assignment attempt from the language, though, is that its effect cannot be achieved with any combination of other existing constructs. The argument, used at other places in this discussion, that infrequently used constructs should be excluded because their replacement by a (less convenient) combination of other constructs is acceptable, cannot be applied here. The assignment attempt is not only a convenient form to express an operation, it is the only form available for these semantics.

We have therefore decided to include the assignment attempt in the language, although this is one of those rare occasions where students must be warned to think very carefully when they use it, about whether its use is really necessary.