2009-12-09 5 views
5

Existe-t-il une méthode recommandée pour modéliser plusieurs niveaux d'héritage en F #, probablement en utilisant une union discriminée?Modélisation de plusieurs niveaux d'héritage en utilisant des unions discriminées

Prendre quelque chose comme ce qui suit en C#:

class Expr { } 
class SourceExpr : Expr { } 
class JoinExpr : SourceExpr { } 
class TableExpr : SourceExpr { } 

Je l'ai fait en F #:

type SourceExpr = 
    | Join of JoinExpr 
    | Table of TableExpr 

type Expr = 
    | Source of SourceExpr 
    | ... 

Y at-il une meilleure façon? Est-ce que cela fournit le même comportement polymorphe que l'héritage?

Répondre

8

Il est difficile d'être trop prescriptif ici sans plus d'informations. En fonction de ce que vous essayez de faire, il peut être plus logique d'utiliser une hiérarchie de classes ou une union discriminée (DU). Les compromis les plus fréquents/les plus évidents sont que les hiérarchies de classes sont «ouvertes» alors que les DU sont «fermées». Autrement dit, vous pouvez facilement ajouter de nouveaux types à une hiérarchie de classes, mais l'ajout d'une nouvelle opération (méthode abstraite sur la classe de base) nécessite la modification de toutes les classes existantes. En revanche, avec les DU, vous pouvez facilement ajouter une nouvelle opération (fonction que le modèle correspond au type de données), mais pour ajouter un nouveau cas (sous-classe) vous devez redéfinir le type et mettre à jour toutes les opérations existantes pour traiter le nouveau cas . (Ceci est parfois appelé "le problème d'expression".)

Un exemple typique qui est bon pour les DU est un compilateur; vous disposez d'un arbre de syntaxe de langage abstrait dans lequel le langage et la structure arborescente sont fixes, mais vous pouvez créer de nombreuses opérations différentes de transformation d'arborescence dans le compilateur. Un exemple typique qui est bon pour les hiérarchies de classe est les frameworks d'interface utilisateur; vous avez une ou plusieurs classe (s) de base qui définissent toutes les opérations que les widgets doivent fournir (Draw, Resize, ...), mais les utilisateurs ajouteront leurs propres sous-types personnalisés avec des capacités supplémentaires.

+0

Je travaille sur un analyseur, donc je pense que les DU sont le bon choix. Mais il y a des expressions qui semblent hériter des autres. Certaines fonctions doivent accepter une jointure ou une table, qui sont toutes deux des sources. Il y a aussi des fonctions qui devraient accepter un Expr, dont Source est l'une des nombreuses options. Je ne peux m'empêcher de penser à cela en termes d'OO, mais je me demande s'il existe une meilleure façon de modéliser cette hiérarchie relativement statique tout en conservant le même type de comportement polymorphe. – Daniel

+0

La modélisation avec les types fonctionnera bien. Si vous avez deux types qui sont "aussi" la même chose, ajoutez un nouveau type qui les différencie et l'utilise. Le seul inconvénient est que vous devrez faire plus de déconstruction, mais la correspondance des motifs et les motifs actifs là où vous en avez besoin rendent cela assez tolérable. Je fais ceci avec quelques types récursifs assez compliqués et un analyseur de FParsec et cela fonctionne plutôt bien. –

0

Vous pouvez modéliser les classes en utilisant l'héritage dans F # comme vous le faites en C# .... OU ... vous pouvez modéliser les exigences en utilisant des unions discriminées comme vous le montrez. Non, les unions discriminées n'autorisent pas le même type de comportement polymorphe, en particulier vous devrez potentiellement modifier toutes les correspondances de modèle si vous ajoutez de nouveaux cas. Il a cependant ses avantages, j'ai tendance à écrire du code avec des unions discriminées en F #, et de l'héritage en C# ... SAUF .... Je suis particulièrement préoccupé par l'extensibilité. Vous ne modélisez aucun niveau d'héritage en utilisant des unions discrimées ... vous comparez des pommes avec des carottes.

Vous pouvez modéliser les mêmes exigences dans les deux paradigmes ... J'irais dans le contexte de l'union discriminée ... Je pense que cela rendra le code plus simple à lire ... mais c'est subjectif.

Questions connexes