Si j'utilise un non scellé trait
ou abstract class
dans Scala et que j'utilise ensuite la correspondance de modèles, je me demande si le compilateur ne sait pas au moment de la compilation pour ce patternmatch particulier quelles implémentations possibles de ce trait / classe sont disponibles? Donc, si c'est le cas, ne pourrait-il pas donner des avertissements de correspondance de modèle même si le trait
/ abstract class
n'est pas scellé parce qu'il sait quels types pourraient être utilisés, en vérifiant toutes les dépendances / importations possibles?
Par exemple, si j'ai un Option[A]
et que je fais une correspondance de modèle uniquement pour Some[A]
mais pas pour None
, le compilateur se plaindra, car il Option
est scellé.
Si le compilateur ne peut pas savoir / résoudre cela, pourquoi ne le peut-il pas? Et si le compilateur (théoriquement) peut le faire, quelles sont les raisons pour lesquelles il n'est pas utilisé dans Scala? Y a-t-il d'autres langues qui prennent en charge ce type de comportement?
la source
Foo
avec des sousA
- classes,,B
etC
, et toutes vos correspondances de modèle ne correspondent qu'à ces trois. Rien ne m'empêche d'ajouter une nouvelle sousD
- classe qui fera exploser vos correspondances de motifs.java.lang.ClassLoader
.Réponses:
La définition de toutes les sous-classes d'une classe est appelée analyse de la hiérarchie des classes, et effectuer un CHA statique dans un langage avec chargement de code dynamique équivaut à résoudre le problème de l'arrêt.
De plus, l'un des objectifs de Scala est la compilation et le déploiement séparés de modules indépendants, de sorte que le compilateur ne peut tout simplement pas savoir si une classe est sous-classée dans un autre module, car il ne regarde jamais plus d'un module. (Après tout, vous pouvez compiler un module par rapport à l'interface d'un autre module sans que ce module n'existe même sur votre système!) C'est pourquoi
sealed
toutes les sous-classes doivent être définies dans la même unité de compilation.C'est également l'une des raisons pour lesquelles les machines virtuelles Java peuvent rivaliser si favorablement avec les compilateurs C ++: les compilateurs C ++ sont généralement des compilateurs statiques, de sorte qu'ils ne peuvent généralement pas déterminer si une méthode est remplacée ou non, et ne peuvent donc pas l'intégrer. Les JVM OTOH sont généralement des compilateurs dynamiques, ils n'ont pas besoin d'effectuer CHA pour déterminer si une méthode est remplacée ou non, ils peuvent simplement regarder la hiérarchie des classes au moment de l'exécution. Et même si, à un stade ultérieur de l'exécution du programme, une nouvelle sous-classe apparaît, qui n'était pas là auparavant, ce n'est pas grave, recompilez simplement ce morceau de code sans l'inliner.
Remarque: tout cela ne s'applique qu'à Scala. La JVM n'a aucune notion de
sealed
, il est donc parfaitement possible de sous-classer lessealed
classes d' un autre langage JVM, car il n'y a aucun moyen de le communiquer à un autre langage. Lasealed
propriété est enregistrée dans l'ScalaSig
annotation, mais les compilateurs d'autres langages ne tiennent pas compte de ces annotations, évidemment.la source
Cela peut être fait (au moins pour toutes les classes connues au moment de la compilation), c'est juste cher. Vous détruiriez complètement la compilation incrémentielle, car tout ce qui contient une correspondance de modèle devrait effectivement être recompilé à chaque changement de fichier.
Et qu'achetez-vous? C'est une odeur de code pour écrire des correspondances de modèle qui doivent changer fréquemment lorsqu'une nouvelle classe dérivée est ajoutée. C'est une violation du principe ouvert / fermé . Utilisez l'héritage correctement et vous n'aurez pas besoin d'écrire ces types de correspondances de modèle. Et oui, le principe ouvert / fermé s'applique également aux langages fonctionnels sans héritage basé sur les classes. En fait, entre des fonctionnalités telles que les classes de types, les méthodes multiples et les fonctions de niveau supérieur, les langages fonctionnels facilitent l'extension sans modification.
la source
It can be done (at least for all classes known at compile time), it's just expensive.
Mais si le programme n'est pas 100% autonome (c'est-à-dire qu'il dépend de.jar
fichiers externes ), ne pourriez-vous pas vous faufiler dans une nouvelle sous-classe après la compilation via l'un desjar
s? Ainsi, le compilateur pourrait vous dire "Vos correspondances de modèles sont exhaustives maintenant, mais cela peut changer si l'une de vos dépendances change", ce qui est assez inutile car le point d'avoir des dépendances externes est de pouvoir les mettre à jour sans recompiler!