eiffel: analysis, design and programming bertrand meyer chair of software engineering

43
Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

Post on 21-Dec-2015

226 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

Eiffel: Analysis, Design and Programming

Bertrand Meyer

Chair ofSoftware Engineering

Page 2: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

2

- 6 -

Genericity

Page 3: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

3

What’s wrong with this code?

class LIST_OF_CARS feature

extend (v: CAR) is …remove (v: CAR) is …item: CAR is …

end

class LIST_OF_CITIES feature

extend (v: CITY) is …

remove (v: CITY) is …

item: CITY is …

end

Page 4: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

4

What’s wrong with this code?

class LIST_OF_CARS featureappend (other: LIST_OF_CARS)

dofrom other.start until other.after loop Current.extend (other.item)end

endend

class LIST_OF_CITIES featureappend (other : LIST_OF_CITIES)

dofrom other.start until other.after loop Current.extend (other.item)end

endend

DRY Principle: Don’t Repeat Yourself

Page 5: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

5

Possible approaches for containers

1. Duplicate code, manually or with help of macro processor.

2. Wait until run time; if types don’t match, trigger a run-time failure. (Smalltalk)

3. Convert (“cast”) all values to a universal type, such as “pointer to void” in C.

4. Parameterize the class, giving an explicit name G to the type of container elements. This is the Eiffel approach, now also found in Java (1.5), .NET (2.0) and others.

Page 6: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

6

Genericity solution to LIST_OF_...

class LIST [G] featureappend (other: LIST [G] ) do

dofrom other.start until other.after

loop Current.extend (other.item)end

endend

city_list: LIST [CITY]car_list: LIST [CAR]

Page 7: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

7

A generic class

class LIST [G ] feature

extend (x : G ) ...

last : G ...

end

To use the class: obtain a generic derivation, e.g.

cities : LIST [CITY ]

Formal generic parameter

Actual generic parameter

Page 8: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

8

Genericity: Ensuring type safety

How can we define consistent “container” data structures, e.g. list of accounts, list of points? Dubious use of a container data structure:

c : CITY ; p : PERSONcities : LIST ... people : LIST ... ---------------------------------------------------------people.extend ( )

cities.extend ( )

c := cities.last

c. some_city_operation

What if wrong?

p

c

Page 9: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

9

Using generic derivations

cities : LIST [CITY ]people : LIST [PERSON]c : CITYp : PERSON...

cities.extend (c)people.extend (p)

c := cities.last

c. some_city_operation

STATIC TYPING

The compiler will reject:

people.extend (c)

cities.extend (p)

Page 10: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

10

Static typing

Type-safe call (during execution):

A feature call x.f such that the object attached to x has a feature corresponding to f.

[Generalizes to calls with

arguments, x.f (a, b) ]

Static type checker:A program-processing tool (such as a compiler) that guarantees, for any program it accepts, that any call in any execution will be type-safe.

Statically typed language:A programming language for which it is possible to write a static type checker.

Page 11: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

11

Using genericity

LIST [CITY ]LIST [LIST [CITY ]]…

A type is no longer exactly the same thing as a class!

(But every type remains based on a class.)

Page 12: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

12

Definition: Type

We use types to declare entities, as in

x : SOME_TYPE

With the mechanisms defined so far, a type is one of:

A non-generic class e.g. METRO_STATION

A generic derivation, i.e. the name of a class followed by a list of types, the actual generic parameters, in brackets (also recursive)

e.g. LIST [ARRAY [METRO_STATION ]]

LIST [LIST [CITY ]]TABLE [STRING, INTEGER]

Page 13: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

13

So, how many types can I possibly get?

Two answers, depending on what we are talking about:

• Static types Static types are the types that we use while writing Eiffel code to declare types for entities (arguments, locals, return values) and when creating new objects without explicitly specifying the type

• Dynamic types Dynamic types on the other hand are created at run-time. Whenever a new object is created, it gets assigned to be of some type.

Page 14: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

14

Static types

class EMPLOYEEfeature

name: STRINGbirthday: DATE

end

class DEPARTMENTfeature

staff: LIST [EMPLOYEE]end

bound by the program text:EMPLOYEE

STRING

DATE

DEPARTMENT

LIST[G]becomes LIST[EMPLOYEE]

Page 15: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

15

Object creation, static and dynamic types

class TEST_DYNAMIC _CREATIONfeature

ref_a: A ref_b: B--Let’s suppose B, with creation feature make_b,

--inherits from A, with creation feature make_a

do_somethingdo

create ref_a.make_a-- All that matters is the static type A

create {B} ref_a.make_b-- This is ok, because of the dynamic

type endend

Page 16: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

16

Dynamic types: another example

class SET[G] feature powerset: SET[SET[G]] is do create Result

-- More computation… end

i_th_power (i: INTEGER): SET[ANY] require i >= 0 local n: INTEGER do Result := Current from n := 1 until n > i loop Result := Result.powerset n := n + 1

end endend __

Dynamic types from i_th_power :

SET[ANY]

SET[SET[ANY]]

SET[SET[SET[ANY]]]

From http://www.eiffelroom.com/article/fun_with_generics

Page 17: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

17

Genericity: summary 1

Type extension mechanism

Reconciles flexibility with type safety

Enables us to have parameterized classes

Useful for container data structures: lists, arrays, trees, …

“Type” now a bit more general than “class”

Page 18: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

18

Extending the basic notion of class

LIST_OF_CARS

BAG_OF_CARS

LINKED_LIST_OF_CARS

LIST_OF_CITIES

LIST_OF_PERSONS

Abstraction

Specialization

Type parameterization

Type parameterization

Genericity

Inheritance

Page 19: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

19

The static and the dynamic

For a feature call x.f :

Static typing:There is at least one feature f applicable to x

Dynamic binding:If more than one possible feature,execution will select the right feature

Page 20: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

20

The static and the dynamic

deferred class ANIMAL featuretalk is

-- Talk, or as least make sound.deferredend

end

class CAT inherit ANIMAL featuretalk is do io.put_string(“Miao”) end

end

class HUMAN inherit ANIMAL featuretalk is do io.put_string(“Hello”) end

end

CAT HUMAN

ANIMAL

Page 21: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

21

The static and the dynamic

a: ANIMALc: CATh: HUMAN

a := ca.talk

a := ha.talk

CAT HUMAN

ANIMAL

When compiling, type checker checks if there is at least one feature named talk in type ANIMAL, which is the declared type of a.

At run-time, execution will select the right feature to invoke, which will be talk from CAT here.

Page 22: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

22

More Genericity

Unconstrained

LIST [G]e.g. LIST [INTEGER], LIST [PERSON]

Constrained

HASH_TABLE [G, H ―> HASHABLE ]

VECTOR [G ―> NUMERIC ]

Page 23: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

23

Genericity + inheritance 1: Constrained genericity

class VECTOR [G ] feature plus alias "+" (other : VECTOR [G]): VECTOR [G]

-- Sum of current vector and otherrequire

lower = other.lower

upper = other.upperlocal

a, b, c: Gdo

... See next ...end

... Other features ...end

Page 24: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

24

Adding two vectors

i a b c=+

+ =u v w

1

2

Page 25: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

25

Constrained genericity

Body of plus alias "+":

create Result.make (lower, upper)

from i := lower

until i > upper

loopa := item (i)b := other.item (i)c := a + b -- Requires “+” operation on G!

Result.put (c, i)i := i + 1

end

Page 26: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

26

The solution

Declare class VECTOR as

class VECTOR [G –> NUMERIC ] feature

... The rest as before ...end

Class NUMERIC (from the Kernel Library) provides features plus alias "+", minus alias "-"and so on.

Page 27: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

27

Improving the solution

Make VECTOR itself a descendant of NUMERIC,

effecting the corresponding features:

class VECTOR [G –> NUMERIC ] inheritNUMERIC

feature... Rest as before, including infix "+"...

endThen it is possible to define

v : VECTOR [INTEGER ]vv : VECTOR [VECTOR [INTEGER ]]vvv : VECTOR [VECTOR [VECTOR [INTEGER ]]]

Page 28: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

28

Enforcing a type: the problem

fl : LINKED_LIST [FIGURE]

fl.store ("FILE_NAME")

...-- Two years later:

fl := retrieved ("FILE_NAME") – See nextx := fl.last -- [1]print (x.diagonal ) -- [2]

What’s wrong with this?

If x is declared of type RECTANGLE, [1] is invalid.If x is declared of type FIGURE, [2] is invalid.

Page 29: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

29

Object-Test Local

Enforcing a type: the Object Test

if {r : RECTANGLE } fl.last then

print (r.diagonal)

… Do anything else with r, guaranteed

… to be non void and of dynamic type RECTANGLE

elseprint ("Too bad.")

end

Expression to be tested

SCOPE of the Object-Test Local

Page 30: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

30

Assignment attempt: an older mechanism

x ?= y

with

x : A

Semantics: If y is attached to an object whose type conforms

to A, perform normal reference assignment.

Otherwise, make x void.

Page 31: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

31

Assignment attempt example

f : FIGUREr : RECTANGLE...

fl.retrieve ("FILE_NAME")

f := fl.last

r ?= f

if r /= Void then

print (r.diagonal)else

print ("Too bad.")end

Page 32: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

32

More examples on constrained generics

deferred class FIGURE featuredraw is

-- Draw Current figuredeferredend

end

class CIRCLE inherit FIGUREfeature

draw do -- Draw circle.end

end

LINE, RECTANGLE, …

Page 33: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

33

What about a composite figure?

class COMPOSITE_FIGUREinherit

feature

end

FIGURE

LINKED_LIST [G]

[G -> FIGURE]

draw

do

-- To be finished.

end

Page 34: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

34

Composite figure

class COMPOSITE_FIGURE [G -> FIGURE] inheritFIGURELINKED_LIST [G]

featuredraw is

dofrom

startuntil

afterloop

item.drawforth

endend

end

Page 35: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

35

Using FIGURE classes

f : FIGUREc1, c2 : CIRCLEl : LINEcc: COMPOSITE_FIGURE [ CIRCLE ]cf: COMPOSITE_FIGURE [ FIGURE ]

cc.extend (c1)cc.extend (c2)cc.draw

cf.extend (c2)cf.extend (l)cf.draw

Page 36: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

36

Are we really type safe?

animal_list: LINKED_LIST [ANIMAL]sheep_list: LINKED_LIST [SHEEP]sheep: SHEEP

sheep_list.extend (sheep)animal_list := sheep_list

SHEEP WOLF

ANIMAL

wolf: WOLF

animal_list.extend (wolf)

Page 37: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

37

CAT calls

CAT stands for Changing Availability or Type

A routine is a CAT if some redefinition changes its export status or the type of any of its arguments

A call is a catcall if some redefinition of the routine would make it invalid because of a change of export status or argument type.

Page 38: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

38

Catcall cases

• Covariant redefinition• Non-generic case• Generic case

• Descendant hiding

Page 39: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

39

Covariant redefinition – Nongeneric case

class ANIMAL feature

eat (a_food: FOOD) is deferred … endend

class WOLFinherit ANIMAL redefine eat endfeature

eat (a_meat: MEAT) is do … endend

MEAT GRASS

FOOD

WOLF

ANIMAL

Page 40: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

40

Covariant redefinition – Nongeneric case

animal: ANIMALwolf: WOLFfood: FOODgrass: GRASS

create wolfcreate grassanimal := wolffood := grassanimal.eat (grass)

MEAT GRASS

FOOD

WOLF

ANIMAL

Page 41: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

41

Descendant hiding

class RECTANGLE inherit

POLYGON export{NONE} add_vertex endend

feature…

invariantvertex_count = 4

end

RECTANGLE

POLYGON

What will happen?

r: RECTANGLE

p: POLYGON

create r

p := r

p.add_vertex (…)

Page 42: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

42

Covariant redefinition – Generic case

animal_list: LINKED_LIST [ANIMAL]sheep_list: LINKED_LIST [SHEEP]sheep: SHEEP

sheep_list.extend (sheep)animal_list := sheep_list

SHEEP WOLF

ANIMAL

wolf: WOLF

animal_list.extend (wolf)

Page 43: Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering

43

Covariant redefinition – Generic case

class LINKED_LIST [ANY]feature

extend (v: ANY) do … endend

class LINKED_LIST [SHEEP]feature

extend (v: SHEEP) do … endend

class LINKED_LIST [WOLF]feature

extend (v: WOLF) do … endend