De nombreux langages comme C++
, C#
et Java
vous permettent de créer des objets qui représentent des types simples comme integer
ou float
. À l'aide d'une interface de classe, vous pouvez remplacer les opérateurs et effectuer une logique telle que la vérification si une valeur dépasse une règle métier de 100.
Je me demande s'il est possible dans certains langages de définir ces règles comme des annotations ou des attributs d'une variable / propriété.
Par exemple, dans C#
vous pourriez écrire:
[Range(0,100)]
public int Price { get; set; }
Ou peut-être que C++
vous pourriez écrire:
int(0,100) x = 0;
Je n'ai jamais rien vu de tel, mais étant donné à quel point nous sommes devenus dépendants de la validation des données avant le stockage. Il est étrange que cette fonctionnalité n'ait pas été ajoutée aux langues.
Pouvez-vous donner un exemple de langues où cela est possible?
la source
data Bool = True | False
et pour ce que vous voulez, vous pourriez diredata Cents = 0 | 1 | 2 | ...
avoir un regardez les "Types de données algébriques" (qui devraient être plus correctement nommés types hindley-milner mais les gens confondent cela avec l'inférence de type de manière ennuyeuse) en.wikipedia.org/wiki/Algebraic_data_typetype
mot - clé dans Pascal après tout. L'orientation des objets est plus un modèle de conception qu'une propriété "atomar" des langages de programmation.Réponses:
Pascal avait des types de sous-gamme, c'est-à-dire une diminution du nombre de nombres qui entrent dans une variable.
Ada a également une notion de plages: http://en.wikibooks.org/wiki/Ada_Programming/Types/range
De Wikipedia ...
peut aussi faire
Et c'est là que ça devient cool
C n'a pas de type de sous-gamme strict, mais il existe des moyens d'en imiter un (au moins limité) en utilisant des champs de bits pour minimiser le nombre de bits utilisés.
struct {int a : 10;} my_subrange_var;}
. Cela peut fonctionner comme une limite supérieure pour le contenu variable (en général, je dirais: n'utilisez pas de champs de bits pour cela , c'est juste pour prouver un point).De nombreuses solutions pour les types entiers de longueur arbitraire dans d'autres langages se produisent plutôt au niveau de la bibliothèque, c'est-à-dire que C ++ permet des solutions basées sur des modèles.
Il existe des langages qui permettent de surveiller les états variables et d'y associer des assertions. Par exemple dans Clojurescript
La fonction
mytest
est appelée quanda
a changé (viareset!
ouswap!
) vérifie si les conditions sont remplies. Cela pourrait être un exemple pour implémenter un comportement de sous-gamme dans des langages à liaison tardive (voir http://blog.fogus.me/2011/09/23/clojurescript-watchers-and-validators/ ).la source
for y in Year_Type loop ...
éliminant les problèmes tels que les dépassements de tampon.Ada est également un langage qui permet des limites pour les types simples, en fait, dans Ada, il est de bonne pratique de définir vos propres types pour votre programme afin de garantir l'exactitude.
Il a été utilisé pendant longtemps par le DoD, peut-être l'est toujours mais j'ai perdu la trace de son utilisation actuelle.
la source
Voir Limitation de la plage de types de valeurs en C ++ pour des exemples de création d'un type de valeur avec plage vérifiée en C ++.
Résumé: utilisez un modèle pour créer un type de valeur qui a des valeurs minimale et maximale intégrées, que vous pouvez utiliser comme ceci:
Vous n'avez même pas vraiment besoin d'un modèle ici; vous pouvez utiliser une classe à effet similaire. L'utilisation d'un modèle vous permet de spécifier le type sous-jacent. En outre, il est important de noter que le type
percent
ci-dessus ne sera pas unfloat
, mais plutôt une instance du modèle. Cela peut ne pas satisfaire l'aspect «types simples» de votre question.Les types simples ne sont que cela - simples. Il est souvent préférable de les utiliser comme blocs de construction pour créer les outils dont vous avez besoin au lieu d'être utilisés directement.
la source
À ma connaissance, une forme restreinte de votre intention est possible en Java et C # grâce à une combinaison d'annotations et de modèle de proxy dynamique (il existe des implémentations intégrées pour les proxys dynamiques en Java et C #).
Version Java
L'annotation:
La classe Wrapper créant l'instance de proxy:
Le InvocationHandler servant de contournement à chaque appel de méthode:
L'exemple d'interface d'utilisation:
Méthode principale:
Production:
Version C #
L'annotation (en C # appelé attribut):
La sous-classe DynamicObject:
La classe d'exemple:
Usage:
En conclusion, vous voyez que vous pouvez faire fonctionner quelque chose comme ça en Java , mais ce n'est pas tout à fait pratique, car
Les capacités de la classe DynamicObject en C # suppriment la restriction d'interface, comme vous le voyez dans l'implémentation C #. Malheureusement, ce comportement dynamique supprime la sécurité de type statique dans ce cas, des vérifications d'exécution sont donc nécessaires pour déterminer si un appel de méthode sur le proxy dynamique est autorisé.
Si ces restrictions sont acceptables pour vous, cela peut servir de base à des recherches supplémentaires!
la source
public virtual int Min { get; private set; }
est une bonne astuce qui raccourcirait considérablement votre codeLes plages sont un cas particulier des invariants. De Wikipédia:
Une plage
[a, b]
peut être déclarée comme une variable x de typeInteger
avec les invariants x> = a et x <= b .Par conséquent, les types de sous-plages Ada ou Pascal ne sont pas strictement nécessaires. Ils pourraient être implémentés avec un type entier avec des invariants.
la source
Les fonctionnalités spéciales pour les types à plage limitée ne sont pas nécessaires en C ++ et dans d'autres langages dotés de systèmes de types puissants.
En C ++, vos objectifs peuvent être atteints relativement simplement avec des types définis par l' utilisateur . Et dans les applications où des types à plage limitée sont souhaitables, ils ne sont guère suffisants . Par exemple, on voudrait également que le compilateur vérifie que les calculs d'unité physique ont été écrits correctement, de sorte que la vitesse / temps produit une accélération et que la racine carrée de l'accélération / temps produise une vitesse. Pour ce faire, il est nécessaire de pouvoir définir un système de types sans nommer explicitement tous les types pouvant apparaître dans une formule. Cela peut être fait en C ++ .
la source