Download presentation
Presentation is loading. Please wait.
2
Eiffel: Analysis, Design and Programming Bertrand Meyer Chair of Software Engineering
3
2 - 6 - Genericity
4
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
5
4 What’s wrong with this code? class LIST_OF_CARS feature append (other: LIST_OF_CARS) do from other.start until other.after loop Current.extend (other.item) end class LIST_OF_CITIES feature append (other : LIST_OF_CITIES) do from other.start until other.after loop Current.extend (other.item) end DRY Principle: Don’t Repeat Yourself
6
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.
7
6 Genericity solution to LIST_OF_... class LIST [G] feature append (other: LIST [G] ) do do from other.start until other.after loop Current.extend (other.item) end city_list: LIST [CITY] car_list: LIST [CAR]
8
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
9
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 : PERSON cities : LIST... people : LIST... --------------------------------------------------------- people. extend ( ) cities. extend ( ) c := cities. last c. some_city_operation What if wrong? p c
10
9 Using generic derivations cities : LIST [CITY ] people : LIST [PERSON] c : CITY p : 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) STATIC TYPING The compiler will reject: people. extend (c) cities. extend (p)
11
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.
12
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.)
13
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]
14
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.
15
14 Static types class EMPLOYEE feature name: STRING birthday: DATE end class DEPARTMENT feature staff: LIST [EMPLOYEE] end bound by the program text: EMPLOYEE STRING DATE DEPARTMENT LIST[G] becomes LIST[EMPLOYEE]
16
15 Object creation, static and dynamic types class TEST_DYNAMIC _CREATION feature ref_a: A ref_b: B --Let’s suppose B, with creation feature make_b, --inherits from A, with creation feature make_a do_something do 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 end end
17
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 __ Dynamic types from i_th_power : SET[ANY] SET[SET[ANY]] SET[SET[SET[ANY]]] … From http://www.eiffelroom.com/article/fun_with_generics
18
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”
19
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 Genericity Inheritance
20
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
21
20 The static and the dynamic deferred class ANIMAL feature talk is -- Talk, or as least make sound. deferred end class CAT inherit ANIMAL feature talk is do io.put_string(“Miao”) end end class HUMAN inherit ANIMAL feature talk is do io.put_string(“Hello”) end end CAT HUMAN ANIMAL
22
21 The static and the dynamic a: ANIMAL c: CAT h: HUMAN a := c a.talk a := h a.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.
23
22 More Genericity Unconstrained LIST [G] e.g. LIST [INTEGER], LIST [PERSON] Constrained HASH_TABLE [G, H ―> HASHABLE ] VECTOR [G ―> NUMERIC ]
24
23 Genericity + inheritance 1: Constrained genericity class VECTOR [G ] feature plus alias "+" (other : VECTOR [G]): VECTOR [G] -- Sum of current vector and other require lower = other. lower upper = other. upper local a, b, c: G do... See next... end... Other features... end
25
24 Adding two vectors + =uvw 1 2
26
25 Constrained genericity Body of plus alias "+": create Result. make (lower, upper) from i := lower until i > upper loop a := item (i) b := other. item (i) c := a + b-- Requires “+” operation on G! Result. put (c, i) i := i + 1 end
27
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.
28
27 Improving the solution Make VECTOR itself a descendant of NUMERIC, effecting the corresponding features: class VECTOR [G –> NUMERIC ] inherit NUMERIC feature... Rest as before, including infix "+"... end Then it is possible to define v : VECTOR [INTEGER ] vv : VECTOR [VECTOR [INTEGER ]] vvv : VECTOR [VECTOR [VECTOR [INTEGER ]]]
29
28 Enforcing a type: the problem fl : LINKED_LIST [FIGURE] fl. store ("FILE_NAME")... -- Two years later: fl := retrieved ("FILE_NAME") – See next x := 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.
30
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 else print ("Too bad.") end Expression to be tested SCOPE of the Object-Test Local
31
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.
32
31 Assignment attempt example f : FIGURE r : RECTANGLE... fl. retrieve ("FILE_NAME") f := fl. last r ?= f if r /= Void then print (r. diagonal) else print ("Too bad.") end
33
32 More examples on constrained generics deferred class FIGURE feature draw is -- Draw Current figure deferred end class CIRCLE inherit FIGURE feature draw do -- Draw circle. end LINE, RECTANGLE, …
34
33 What about a composite figure? class COMPOSITE_FIGURE inherit feature end FIGURE LINKED_LIST [G] [G -> FIGURE] draw do -- To be finished. end
35
34 Composite figure class COMPOSITE_FIGURE [G -> FIGURE] inherit FIGURE LINKED_LIST [G] feature draw is do from start until after loop item.draw forth end
36
35 Using FIGURE classes f : FIGURE c1, c2 : CIRCLE l : LINE cc: COMPOSITE_FIGURE [ CIRCLE ] cf: COMPOSITE_FIGURE [ FIGURE ] cc.extend (c1) cc.extend (c2) cc.draw cf.extend (c2) cf.extend (l) cf.draw
37
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 SHEEPWOLF ANIMAL wolf: WOLF animal_list.extend (wolf)
38
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.
39
38 Catcall cases Covariant redefinition Non-generic case Generic case Descendant hiding
40
39 Covariant redefinition – Nongeneric case class ANIMAL feature eat (a_food: FOOD) is deferred … end end class WOLF inherit ANIMAL redefine eat end feature eat (a_meat: MEAT) is do … end end MEAT GRASS FOOD WOLF ANIMAL
41
40 Covariant redefinition – Nongeneric case animal: ANIMAL wolf: WOLF food: FOOD grass: GRASS create wolf create grass animal := wolf food := grass animal.eat (grass) MEAT GRASS FOOD WOLF ANIMAL
42
41 Descendant hiding class RECTANGLE inherit POLYGON export{NONE} add_vertex end end feature … invariant vertex_count = 4 end RECTANGLE POLYGON What will happen? r: RECTANGLE p: POLYGON create r p := r p.add_vertex (…)
43
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 SHEEPWOLF ANIMAL wolf: WOLF animal_list.extend (wolf)
44
43 Covariant redefinition – Generic case class LINKED_LIST [ANY] feature extend (v: ANY) do … end end class LINKED_LIST [SHEEP] feature extend (v: SHEEP) do … end end class LINKED_LIST [WOLF] feature extend (v: WOLF) do … end end
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.