Difference between revisions of "Forget / Keep Mechanism"

m (Conformance)
Line 229: Line 229:
 
===Arguments with like===
 
===Arguments with like===
  
A declaration <e>like Current</e> is a covariant redefinition for all subtypes. Since this occurs in <e>ANY.is_equal</e> and <e>ANY.copy</e>, every class has a covariantly redefined fetaures.
+
A declaration <e>like Current</e> is a covariant redefinition for all subtypes.
 
+
<e>
+
class ANY
+
 
+
feature
+
 
+
  is_equal (other: like Current): BOOLEAN
+
 
+
  copy (other: like Current)
+
 
+
end
+
</e>
+
  
 
==Feature hiding==
 
==Feature hiding==
Line 379: Line 367:
 
===ANY===
 
===ANY===
  
Since <e>ANY</e> has features with <e>like Current</e> arguments, the default mechanism for forgetting or keeping features has an impact on the bevaiour of <e>ANY</e> and thus all types.
+
<e>ANY</e> has the features <e>ANY.is_equal</e> and <e>ANY.copy</e> with a <e>like Current</e> argument:
 +
 
 +
<e>
 +
class ANY
 +
 
 +
feature
 +
 
 +
  is_equal (other: like Current): BOOLEAN
 +
 
 +
  copy (other: like Current)
 +
 
 +
end
 +
</e>
 +
 
 +
Since all types are descendants of <e>ANY</e>, all types have covariantly redefined features. The choice of default for the forget mechanism has thus an impact on the whole type hierarchy:
  
 
If the default is forgetting all features (poly) than you will be able to assign all types to <e>ANY</e>, but the features <e>is_equal</e> and <e>copy</e> will not be available since they are covariantly redefined.
 
If the default is forgetting all features (poly) than you will be able to assign all types to <e>ANY</e>, but the features <e>is_equal</e> and <e>copy</e> will not be available since they are covariantly redefined.
Line 385: Line 387:
 
If the default is keeping all featurs (mono) than no type will conform to <e>ANY</e> and thus all assignments to <e>ANY</e> from any other type are illegal.
 
If the default is keeping all featurs (mono) than no type will conform to <e>ANY</e> and thus all assignments to <e>ANY</e> from any other type are illegal.
  
'''''Solution''''': change the argument of <e>is_equal</e> and <e>copy</e> to type <e>ANY</e> and introduce add a precondition to require conformance of argument and object.
+
'''''Solution''''': change the argument of <e>is_equal</e> and <e>copy</e> to type <e>ANY</e>. Then either introduce a precondition to require conformance of argument and object or add a type checks to the actual implementation of the features.
  
 
===SET.has===
 
===SET.has===
  
 
...
 
...

Revision as of 08:17, 20 February 2007

Warning.png Warning: Warning: Article under development

Introduction

By allowing covariant feature redefinition and hiding of features, the Eiffel language introduces the problem of cat-calls. The forget mechanism tries to prevent this by introducing new derived types whenever a feature is covariantly redefined or the export status restricted. These derived types are then used to prevent cat-calls through the conformance rules to the original types.

Example

The following classes will be used for illustration:

class ANIMAL
 
feature
 
  eat (f: FOOD)
 
  sleep
 
end
class CAT
 
inherit
 
  ANIMAL
    redefine
      eat
    export
      {NONE} sleep
    end
 
feature
 
  eat (f: CAT_FOOD)
 
end
class FOOD
 
end
 
class CAT_FOOD
 
inherit
 
  FOOD
 
end
class SET [G]
 
feature
 
  has (g: G): BOOLEAN
 
  put (g: G)
 
  item: G
 
end
class LIST [G]
 
inherit 
 
  SET [G]
 
end

Forget mechanism

...

Conformance

The conformance between ANIMAL, ANIMAL forget eat, ANIMAL forget sleep and ANIMAL forget all is as follows:

local
  normal_animal: ANIMAL
  forget_eat_animal:   ANIMAL forget eat end
  forget_sleep_animal: ANIMAL forget sleep end
  forget_all_animal:   ANIMAL forget all end
do
    -- these assignments are legal since all features present in the
    -- forget types are also present in the normal type
  forget_eat_animal   := normal_animal
  forget_sleep_animal := normal_animal
  forget_all_animal   := normal_animal
 
    -- these assignment are illegal since the forget types lack
    -- at least one feature and thus cannot be used as an ANIMAL
  normal_animal := forget_eat_animal
  normal_animal := forget_sleep_animal
  normal_animal := forget_all_animal
 
    -- these assignments are legal since the forget all type
    -- has fewer or equal features than the other forget types
  forget_all_animal := forget_eat_animal
  forget_all_animal := forget_sleep_animal
 
    -- these assignments are illegal since the forget all type
    -- lacks one feature that the other types have (eat or sleep
    -- respectively)
  forget_eat_animal := forget_all_animal
  forget_sleep_animal := forget_all_animal
 
    -- these assignments are illegal since both types lack
    -- a feature which the other type has
  forget_eat_animal := forget_sleep_animal
  forget_sleep_animal := forget_eat_animal
 
end

Default behaviour

...

Covariant feature redefinition

Cat-call problem

With covariant feature redefinition you run into cat-call problems as this example shows:

local
  a: ANIMAL
  c: CAT
  food: FOOD
do
 
  a := c
    -- eat for type CAT takes arguments only of type CAT_FOOD
  a.eat (food)
 
end

With forget mechanism

Types which have covariant redefined features will not be conform. A feature which is covariantly redefined changes its inherit clause implicitly to inherit from a parent class which has the redefined feature in a forget clause.

what you write what is implied
class CAT
 
inherit
 
  ANIMAL
    redefine
      eat
    end
 
feature
 
  eat (f: CAT_FOOD)
 
end
class CAT
 
inherit
 
  ANIMAL
    forget 
      eat
    redefine
      eat
    end
 
feature
 
  eat (f: CAT_FOOD)
 
end

Now the cat-call example with the new forget types:

local
  a: ANIMAL
  c: CAT
do
    -- illegal assignment, ANIMAL and CAT don't conform
    -- since CAT implicitly inherits from ANIMAL forget eat
  a := c
  a.eat (food)
 
end
local
  a: ANIMAL forget all end
  c: CAT
do
    -- legal, CAT conforms to ANIMAL forget all
  a := c
 
    -- illegal, ANIMAL forget all doesn't have a feature eat
  a.eat (food)
 
end

Arguments with like

A declaration like Current is a covariant redefinition for all subtypes.

Feature hiding

Cat-call problem

By changing the export status of features, a cat-call problem is introduced:

local
  a: ANIMAL
  c: CAT
do
 
  a := c
    -- sleep is hidden for type CAT and should not be called
  a.sleep
 
end

With forget mechanism

When you change the export status of a feature, you implicitly change the inherit clause to inherit from a type which has the specific feature in a forget clause.

what you write what is implied
class CAT
 
inherit
 
  ANIMAL
    export
      {NONE} sleep
    end
 
end
class CAT
 
inherit
 
  ANIMAL
    forget 
      sleep
    export
      {NONE} sleep
    end
 
end

Now the cat-call example:

local
  a: ANIMAL
  c: CAT
do
    -- illegal assignment, ANIMAL and CAT don't conform
    -- since CAT implicitly inherits from ANIMAL forget sleep
  a := c
  a.sleep
 
end
local
  a: ANIMAL forget all end
  c: CAT
do
    -- legal, CAT conforms to ANIMAL forget all
  a := c
 
    -- illegal, ANIMAL forget all doesn't have a feature sleep
  a.sleep
 
end

Generics

...

Syntax

The first variant has the default on NOT forgetting features, thus breaking conformance between the type and its subclasses which use covariant redefinition.

-- normal declaration is an object with all features and no
  -- subtype which has a covariantly redefined feature conforms to this type
a1: ANIMAL
 
  -- a type marked as `poly' will loose all covarianlty redefined features
  -- and all subtypes conform to this type
a2: poly ANIMAL
 
  -- a type which only forgets the features `eat' and `drink' but not other
  -- covarianlty redefined features. all subtypes which only redefine `eat' or
  -- `drink' will conform to this type
a3: ANIMAL forget eat, drink end
 
  -- a type which forgets all covariantly redefined features. equivalent to `poly'
a4: ANIMAL forget all end

The second variant has the default on forgetting all features which are covariantly redefined, thus keeping conformance with subtypes.

-- normal declaration is an object which forgets all covariantly
  -- redefined features. all subtypes conform to this type
b1: ANIMAL
 
  -- a type which keeps all features and looses conformance from subtypes which
  -- covariantly redefine features
b2: mono ANIMAL
 
  -- a type where all subtypes conform except those who covariantly redefine
  -- feature `eat'
b3: ANIMAL keep eat end
 
  -- a type which keeps all features. equivalent to `mono'
b4: ANIMAL keep all end

Consequences

ANY

ANY has the features ANY.is_equal and ANY.copy with a like Current argument:

class ANY
 
feature
 
  is_equal (other: like Current): BOOLEAN
 
  copy (other: like Current)
 
end

Since all types are descendants of ANY, all types have covariantly redefined features. The choice of default for the forget mechanism has thus an impact on the whole type hierarchy:

If the default is forgetting all features (poly) than you will be able to assign all types to ANY, but the features is_equal and copy will not be available since they are covariantly redefined.

If the default is keeping all featurs (mono) than no type will conform to ANY and thus all assignments to ANY from any other type are illegal.

Solution: change the argument of is_equal and copy to type ANY. Then either introduce a precondition to require conformance of argument and object or add a type checks to the actual implementation of the features.

SET.has

...