Difference between revisions of "Forget / Keep Mechanism"
Line 85: | Line 85: | ||
The forget mechanism introduces a new keyword <e>forget</e> which can be used to remove covarianlty redefined features and features which change the export status. By removing features, a new type is introduced. The new type has all features the original type has except those listed in the forget clause. If <e>forget all</e> is used, all features which are covariantly redefined or have a changed export status will be removed from the new type. | The forget mechanism introduces a new keyword <e>forget</e> which can be used to remove covarianlty redefined features and features which change the export status. By removing features, a new type is introduced. The new type has all features the original type has except those listed in the forget clause. If <e>forget all</e> is used, all features which are covariantly redefined or have a changed export status will be removed from the new type. | ||
+ | |||
+ | ===Default behaviour=== | ||
+ | |||
+ | In the forget mechanism the normal declaration of a type will keep all covariantly redefined features or features whose export status is restricted. This implies that all subtypes which change an export status or covariantly redefine a feature don't conform to this type anymore. | ||
+ | |||
+ | <e> | ||
+ | local | ||
+ | animal: ANIMAL | ||
+ | cat: CAT | ||
+ | do | ||
+ | -- legal since the feature `eat' is available in the normal type | ||
+ | animal.eat (food) | ||
+ | |||
+ | -- legal since the feature `sleep' is available in the normal type | ||
+ | animal.sleep | ||
+ | |||
+ | -- illegal since CAT inherits from ANIMAL forget eat | ||
+ | animal := cat | ||
+ | end | ||
+ | </e> | ||
+ | |||
+ | ===Syntax=== | ||
+ | |||
+ | <e> | ||
+ | -- 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 | ||
+ | </e> | ||
===Conformance=== | ===Conformance=== | ||
Line 134: | Line 174: | ||
The keep mechanism is the contrary to the forget mechanism. It introduces a new keyword <e>keep</e> which can be used to keep covarianlty redefined features and features which change the export status. | The keep mechanism is the contrary to the forget mechanism. It introduces a new keyword <e>keep</e> which can be used to keep covarianlty redefined features and features which change the export status. | ||
+ | |||
+ | ===Default behaviour=== | ||
+ | |||
+ | In the keep mechanism the normal declaration of a type will loose all covariantly redefined features or features whose export status is restricted. This implies that all subtypes still conform to a normally declared type. | ||
+ | |||
+ | <e> | ||
+ | local | ||
+ | animal: ANIMAL | ||
+ | cat: CAT | ||
+ | do | ||
+ | -- illegal since the feature `eat' is covariantly redefined | ||
+ | animal.eat (food) | ||
+ | |||
+ | -- illegal since the feature `sleep' changes export status | ||
+ | animal.sleep | ||
+ | |||
+ | -- legal since animal has no problematic features | ||
+ | animal := cat | ||
+ | end | ||
+ | </e> | ||
+ | |||
+ | ===Syntax=== | ||
+ | |||
+ | <e> | ||
+ | -- 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 | ||
+ | </e> | ||
===Conformance=== | ===Conformance=== | ||
Line 375: | Line 454: | ||
... | ... | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
==Consequences== | ==Consequences== |
Revision as of 13:46, 20 February 2007
Warning: Warning: Article under development
Contents
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
The forget mechanism introduces a new keyword forget
which can be used to remove covarianlty redefined features and features which change the export status. By removing features, a new type is introduced. The new type has all features the original type has except those listed in the forget clause. If forget all
is used, all features which are covariantly redefined or have a changed export status will be removed from the new type.
Default behaviour
In the forget mechanism the normal declaration of a type will keep all covariantly redefined features or features whose export status is restricted. This implies that all subtypes which change an export status or covariantly redefine a feature don't conform to this type anymore.
local animal: ANIMAL cat: CAT do -- legal since the feature `eat' is available in the normal type animal.eat (food) -- legal since the feature `sleep' is available in the normal type animal.sleep -- illegal since CAT inherits from ANIMAL forget eat animal := cat end
Syntax
-- 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
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 -- this is equivalent to the forget all clause as long as -- no other features of ANIMAL are covarianlty redefined forget_eat_sleep_animal: ANIMAL forget eat, sleep 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 has (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
Keep mechanism
The keep mechanism is the contrary to the forget mechanism. It introduces a new keyword keep
which can be used to keep covarianlty redefined features and features which change the export status.
Default behaviour
In the keep mechanism the normal declaration of a type will loose all covariantly redefined features or features whose export status is restricted. This implies that all subtypes still conform to a normally declared type.
local animal: ANIMAL cat: CAT do -- illegal since the feature `eat' is covariantly redefined animal.eat (food) -- illegal since the feature `sleep' changes export status animal.sleep -- legal since animal has no problematic features animal := cat end
Syntax
-- 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
Conformance
The conformance between ANIMAL
, ANIMAL keep eat
, ANIMAL keep sleep
and ANIMAL keep all
is as follows:
local normal_animal: ANIMAL keep_eat_animal: ANIMAL keep eat end keep_sleep_animal: ANIMAL keep sleep end keep_all_animal: ANIMAL keep all end -- this is equivalent to the keep all clause as long as -- no other features of ANIMAL are covarianlty redefined keep_eat_sleep_animal: ANIMAL keep eat, sleep end do -- these assignments are illegal since the normal ANIMAL type -- does not have the eat or sleep features keep_eat_animal := normal_animal keep_sleep_animal := normal_animal keep_all_animal := normal_animal -- these assignment are legal since the normal type has -- fewer features than the keep types normal_animal := keep_eat_animal normal_animal := keep_sleep_animal normal_animal := keep_all_animal -- these assignments are illegal since the keep all type -- has more features than the other keep types keep_all_animal := keep_eat_animal keep_all_animal := keep_sleep_animal -- these assignments are legal since the keep all type -- has more features than the other keep types keep_eat_animal := keep_all_animal keep_sleep_animal := keep_all_animal -- these assignments are illegal since both types lack -- a feature which the other type has keep_eat_animal := keep_sleep_animal keep_sleep_animal := keep_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
...
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.
export {NONE} all
...
SET.has
...