Eiffel: Analysis, Design and Programming
This presentation is the property of its rightful owner.
Sponsored Links
1 / 43

Eiffel: Analysis, Design and Programming Bertrand Meyer PowerPoint PPT Presentation


  • 55 Views
  • Uploaded on
  • Presentation posted in: General

Eiffel: Analysis, Design and Programming Bertrand Meyer. Chair of Software Engineering. - 6 - Genericity. 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

Download Presentation

Eiffel: Analysis, Design and Programming Bertrand Meyer

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Eiffel analysis design and programming bertrand meyer

Eiffel: Analysis, Design and Programming

Bertrand Meyer

Chair ofSoftware Engineering


Eiffel analysis design and programming bertrand meyer

- 6 -

Genericity


What s wrong with this code

What’s wrong with this code?

  • classLIST_OF_CARSfeature

  • extend (v: CAR) is …

  • remove (v: CAR) is …

  • item: CARis …

  • end

classLIST_OF_CITIESfeature

extend (v: CITY) is …

remove (v: CITY) is …

item: CITYis …

end


What s wrong with this code1

What’s wrong with this code?

  • classLIST_OF_CARSfeature

  • append (other: LIST_OF_CARS)

  • do

  • from other.start until other.after loop

  • Current.extend (other.item)

  • end

  • end

  • end

  • classLIST_OF_CITIESfeature

  • append (other : LIST_OF_CITIES)

  • do

  • from other.start until other.after loop

  • Current.extend (other.item)

  • end

  • end

  • end

DRY Principle: Don’t Repeat Yourself


Possible approaches for containers

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.


Genericity solution to list of

Genericity solution to LIST_OF_...

  • classLIST [G]feature

  • append (other: LIST [G]) do

  • do

  • from other.start until other.after loop

  • Current.extend (other.item)

  • end

  • end

  • end

  • city_list: LIST [CITY]

  • car_list: LIST [CAR]


A generic class

A generic class

classLIST[G ]featureextend (x : G )...last : G ...end

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

cities: LIST[CITY ]

Formal generic parameter

Actual generic parameter


Genericity ensuring type safety

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


Using generic derivations

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

Static typing

Type-safe call (during execution):

A feature call x.fsuch 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.


Using genericity

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.)


Definition type

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]


So how many types can i possibly get

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.


Static types

Static types

  • classEMPLOYEE

  • feature

  • name: STRING

  • birthday: DATE

  • end

  • classDEPARTMENT

  • feature

  • staff: LIST [EMPLOYEE]

  • end

bound by the program text:

EMPLOYEE

STRING

DATE

DEPARTMENT

LIST[G]

becomes LIST[EMPLOYEE]


Object creation static and dynamic types

Object creation, static and dynamic types

  • classTEST_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

  • createref_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


Dynamic types another example

Dynamic types: another example

  • classSET[G] feature

  • powerset:SET[SET[G]]is

  • do

  • createResult

  • -- More computation…

  • end

  • i_th_power(i: INTEGER):SET[ANY]

  • require i>=0

  • local n:INTEGER

  • do

  • Result:=Current

  • fromn:=1untiln>iloop

  • Result:=Result.powerset

  • n:=n+1

  • end

  • end

  • 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


Genericity summary 1

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”


Extending the basic notion of class

Extending the basic notion of class

BAG_OF_CARS

LIST_OF_CITIES

LIST_OF_

PERSONS

LINKED_LIST_OF_CARS

Inheritance

Abstraction

Genericity

Type parameterization

Type parameterization

LIST_OF_CARS

Specialization


The static and the dynamic

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


The static and the dynamic1

The static and the dynamic

  • deferredclassANIMAL feature

  • talkis

  • -- Talk, or as least make sound.

  • deferred

  • end

  • end

  • classCAT inherit ANIMAL feature

  • talkis do io.put_string(“Miao”) end

  • end

  • classHUMAN inherit ANIMAL feature

  • talkis do io.put_string(“Hello”) end

  • end

ANIMAL

HUMAN

CAT


The static and the dynamic2

The static and the dynamic

  • a: ANIMAL

  • c: CAT

  • h: HUMAN

  • a := c

  • a.talk

  • a := h

  • a.talk

ANIMAL

HUMAN

CAT

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 fromCAT here.


More genericity

More Genericity

Unconstrained

LIST[G]

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

Constrained

HASH_TABLE[G, H―> HASHABLE]

VECTOR [G―> NUMERIC]


Genericity inheritance 1 constrained genericity

Genericity + inheritance 1: Constrained genericity

  • class VECTOR [G ] feature

  • plusalias "+" (other: VECTOR [G]): VECTOR [G]

  • -- Sum of current vector andother

  • require

  • lower = other.lower

  • upper = other.upper

  • local

  • a, b, c: G

  • do

  • ... See next ...

  • end

  • ... Other features ...

  • end


Adding two vectors

=

i

c

a

b

+

Adding two vectors

u

v

=

w

+

2

1


Constrained genericity

Constrained genericity

  • Body of plusalias "+":

  • createResult.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


The solution

The solution

  • Declare class VECTOR as

  • classVECTOR [G –>NUMERIC] feature

    ... The rest as before ...

  • end

  • Class NUMERIC (from the Kernel Library) provides features plusalias "+", minusalias "-"and so on.


Improving the solution

Improving the solution

  • Make VECTOR itself a descendant of NUMERIC,

  • effecting the corresponding features:

  • classVECTOR [G –> NUMERIC] inherit

  • NUMERIC

  • feature

  • ... Rest as before, includinginfix"+"...

  • end

  • Then it is possible to define

  • v : VECTOR [INTEGER]

  • vv : VECTOR [VECTOR [INTEGER]]

  • vvv: VECTOR [VECTOR [VECTOR [INTEGER]]]


Enforcing a type the problem

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.


Enforcing a type the object test

Enforcing a type: the Object Test

Expression to be tested

Object-Test Local

  • if {r: RECTANGLE} fl.lastthenprint (r.diagonal)

  • … Do anything else with r, guaranteed

  • … to be non void and of dynamic type RECTANGLE

  • elseprint ("Too bad.")

  • end

SCOPEof the Object-Test Local


Assignment attempt an older mechanism

Assignment attempt: an older mechanism

  • x ?= y

  • with

  • x: A

  • Semantics:

    • Ifyis attached to an object whose type conforms to A, perform normal reference assignment.

    • Otherwise, make xvoid.


Assignment attempt example

Assignment attempt example

  • f: FIGURE

  • r: RECTANGLE

  • ...

  • fl.retrieve ("FILE_NAME")

  • f := fl.last

  • r ?= f

  • ifr /= Void thenprint (r.diagonal)elseprint ("Too bad.")end


More examples on constrained generics

More examples on constrained generics

  • deferredclassFIGUREfeature

  • drawis

  • -- Draw Current figure

  • deferred

  • end

  • end

  • classCIRCLEinheritFIGURE

  • feature

  • drawdo -- Draw circle.

  • end

  • end

  • LINE, RECTANGLE, …


What about a composite figure

What about a composite figure?

[G -> FIGURE]

  • classCOMPOSITE_FIGURE

  • inherit

  • feature

  • end

FIGURE

LINKED_LIST[G]

  • draw

  • do

  • -- To be finished.

  • end


Composite figure

Composite figure

  • classCOMPOSITE_FIGURE[G->FIGURE] inherit

  • FIGURE

  • LINKED_LIST[G]

  • feature

  • drawis

  • do

  • from

  • start

  • until

  • after

  • loop

  • item.draw

  • forth

  • end

  • end

  • end


Using figure classes

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


Are we really type safe

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

ANIMAL

SHEEP

WOLF

wolf: WOLF

animal_list.extend (wolf)


Cat calls

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.


Catcall cases

Catcall cases

  • Covariant redefinition

    • Non-generic case

    • Generic case

  • Descendant hiding


Covariant redefinition nongeneric case

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

ANIMAL

WOLF

FOOD

GRASS

MEAT


Covariant redefinition nongeneric case1

Covariant redefinition – Nongeneric case

  • animal: ANIMAL

  • wolf: WOLF

  • food: FOOD

  • grass: GRASS

  • create wolf

  • create grass

  • animal := wolf

  • food := grass

  • animal.eat (grass)

ANIMAL

WOLF

FOOD

GRASS

MEAT


Descendant hiding

Descendant hiding

  • classRECTANGLE

  • inherit

  • POLYGON

  • export{NONE} add_vertexend

  • end

  • feature

  • invariant

  • vertex_count = 4

  • end

POLYGON

RECTANGLE

What will happen?

r: RECTANGLE

p: POLYGON

create r

p := r

p.add_vertex (…)


Covariant redefinition generic case

Covariant redefinition – Generic case

  • animal_list: LINKED_LIST [ANIMAL]

  • sheep_list: LINKED_LIST [SHEEP]

  • sheep: SHEEP

  • sheep_list.extend (sheep)

  • animal_list := sheep_list

ANIMAL

SHEEP

WOLF

wolf: WOLF

animal_list.extend (wolf)


Covariant redefinition generic case1

Covariant redefinition – Generic case

  • classLINKED_LIST [ANY]

  • feature

  • extend (v: ANY) do … end

  • end

  • classLINKED_LIST [SHEEP]

  • feature

  • extend (v: SHEEP) do … end

  • end

  • classLINKED_LIST [WOLF]

  • feature

  • extend (v: WOLF) do … end

  • end


  • Login