Généralement, un programme OCaml peut être écrit avec ou sans objets. Quand est-il préférable d'utiliser des objets et quand doivent-ils être évités?
Réponse
Trop de publicités?Comme une règle générale, ne pas utiliser des objets. La complexité supplémentaire qu'ils apportent n'est pas souvent la peine. Je pense que c'est une règle qui s'applique à d'autres langues, mais c'est une autre histoire. Au moins avec OCaml, on peut objectivement (no pun intended) dire que la pratique courante est de ne pas utiliser d'objet, sauf dans de rares cas.
Objet de fournir un paquet de:
- Un "standard" de style pour le transport autour et à l'aide des enregistrements de fonctions, avec éventuellement des types polymorphes
- Installations pour ouvrir la récursivité par
self
(mise en œuvre de l'héritage) - Un structurels, extensible type de produit avec la ligne de polymorphisme (pour ouvrir les types d'objet) et le sous-typage (pour les types d'objet)
Vous pouvez utiliser ces ensemble, ou séparément.
Dans mon expérience, point (1) seul n'est pas particulièrement intéressant de l'utilisation des objets: vous pouvez tout simplement utiliser les fiches de fonctions et il est tout aussi clair.
Cas d'utilisation de l'Open Récursive / l'Héritage
Le Point (2), au contraire, est une bonne justification pour l'utilisation d'un objet style orienté; il est utilisé de cette manière par les Camlp4 par exemple: Camlp4 de définir des classes qui se replient sur un AST de ne rien faire, et vous pouvez hériter de cette traversée de l'objet à mettre en œuvre le comportement que vous souhaitez uniquement sur les constructions syntaxiques que vous voulez (et de reporter l'alésage de la traversée de la plomberie de votre classe mère).
Par exemple, on peut étendre la Camlp4Ast.la carte de l'objet, qui définit une simple fonction map sur le Camlp4 représentation de l'OCaml arbre de Syntaxe Abstraite, juste cartographie de tous les construire pour lui-même, de manière récursive. Si vous voulez, disons, une carte de tous les (fun x -> e1) e2
expressions d' let x = e2 in e1
, vous héritez de cet objet, et de remplacer l' expr
méthode, la manipulation n'est le cas que vous voulez (partie gauche est une fonction), la délégation de l'autre à l'héritage de comportement. Cela vous donnera un objet qui sait comment appliquer cette transformation sur un programme complet, de manière récursive, sans avoir à écrire du code réutilisable; et vous pouvez encore étendre cette transformation avec un comportement supplémentaire si vous le souhaitez.
Du plaisir avec les types d'objet
Le Point (3) est également une justification à l'utilisation d'objets comme "extensible records", ou comme "au niveau du type de matrices"; certaines bibliothèques au moyen d'objets de types, mais pas de l'objet au moment de l'exécution: ils utilisent des types d'objets et types fantômes à transporter de l'information, bénéficiant de la plus riche au niveau du type d'opérations que vous pouvez avoir sur les objets. En outre, structurelles tapant permettre différents auteurs à avoir des types compatibles sans de fortes dépendances d'une composante commune de la définition de l' (nominale) des types qu'ils partagent; les objets ont été utilisés pour la normalisation des entrées/sorties des composants par exemple.
Un non-rare, très simple cas d'utilisation de ce est une idiomatiques manière de représenter des types qui ont un grand nombre de paramètres. Au lieu d'écrire:
type ('name, 'addr, 'job, 'id) person = ....
val me : (string, string, Job.t, Big_int.big_int) person
vous pouvez utiliser les types d'objet structurelle "type de données au niveau de l'" pour écrire à la place:
type 'a person = .... constraint 'a = < name:'n; addr:'a; job:'j; id:'i >
val me : < name:string; addr:string; job:Job.t; id:Big_int.big_int > person
Pour les plus avancés utilisation de types d'objets et types fantômes, vous pouvez avoir un coup d'oeil à la ShCaml (doc) bibliothèque (où il est utilisé pour représenter le shell de commandes d'une chaîne d'entrée est compatible avec) par Alec Heller et Jesse Tov, ou mon propre Macaque bibliothèque (doc et doc api), qui utilise les types d'objet pour représenter SQL valeurs (y compris la possibilité de valeur null de l'information) et de la table des types de ligne.
Variantes polymorphes (une autre fonctionnalité avancée de OCaml type de système; dans une phrase, la relation entre les objets et dossiers est la même que la relation entre les variantes polymorphes et de la somme algébrique de types).ont également été utilisés comme types fantômes, par exemple dans cet exemple simple par Richard Jones, ou de vérifier la validité des documents HTML dans le Ocsigen cadre.
Méfiez-vous cependant que ces avancées type hackeries venir à un coût de complexité; avant de les utiliser, vous devez soigneusement en balance avec l'expressivité supplémentaire et statique de la sécurité qu'ils apportent.
Résumé
comme hypothèse de base, vous êtes en sécurité avec la non utilisation d'objets à tous; vous ne devez les introduire dans votre conception si vous sentez que vous manquez quelque chose, pas par défaut
les objets sont pratiques pour ouvrir la récursivité / l'héritage: raffinage d'un comportement qui est déjà défini dans le répertoire par défaut/ennuyeux cas
structurelles de frappe est parfois utile quand vous voulez à la raison sur les valeurs indépendamment de fournir un ensemble de caractéristiques/capacités