2016-12-13 4 views
0

(Souligné par l'auteur)Eiffel: types illégaux Covariant passés en arguments?

Covariant redefinition of fields and functions provides no problems, but covariant redefinition of arguments does create a problem that illegal types can be passed as arguments.

Mais, si redéfinissant les champs et les types fonction provoque covariante aucun problème, alors comment se fait redéfinir le type d'argument peut covariante causer des problèmes?

La redéfinition covariante est égale au sous-typage, n'est-ce pas? Et les sous-types peuvent prendre la place de leurs supertypes!

Quel est le piège?

Répondre

1

Le problème n'est pas la covariance elle-même. (En particulier, s'il y avait contra-variance, Design-by-Contract serait impossible, car les types d'arguments dans les caractéristiques des classes descendantes n'auraient pas forcément de caractéristiques disponibles chez leurs parents, avec covariance il n'y a pas de problème.)

Problematic est une combinaison de covariance et de polymorphisme. Par exemple.

class A feature 
    foo (a: A) do a.bar end -- (1) 
    bar do end 
end 
class B inherit A redefine foo end feature 
    foo (a: B) do a.qux end -- (2) 
    qux do end 
end 

maintenant le code suivant plantait:

a: A; b: B 
... 
create b 
a := b 
a.foo (create {A}) 

En effet, a.foo appellerait la version (2) parce que a est attaché à un objet de type B. Toutefois, l'argument transmis à cette fonctionnalité sera de type A. Et A n'a aucune fonctionnalité qux qui conduit à une erreur d'exécution. Ce type d'erreur est appelé appel CAT (Modification de la disponibilité ou type).

Une solution à ce problème consiste à éviter d'utiliser la covariance avec le polymorphisme, c'est-à-dire qu'un appel ne devrait pas être polymorphe ou qu'il ne devrait pas y avoir de redéclaration d'arguments covariante. Le travail sur cette solution est en cours.

0

"un appel ne devrait pas être polymorphe ou il ne devrait pas y avoir de redéclaration covariante d'arguments."

Comment pouvez-vous dire?

Changeons votre exemple un peu:

buzz (une_une: A) do a_a.foo (créer {A}) fin

Cela semble assez innocent. Mais si buzz reçoit un argument de type B dynamique, vous obtenez toujours le catcall. L'auteur du buzz pourrait bien être dans une situation où l'existence de B est inconnue.

Je pense que vous avez besoin de laisser tomber le "un appel ne devrait pas être polymorphe ou" un peu du conseil. Il suffit d'interdire la redéclaration covariante des arguments.