Muchos idiomas C++
, como , C#
y le Java
permiten crear objetos que representan tipos simples como integer
o float
. Usando una interfaz de clase, puede anular operadores y realizar lógica como verificar si un valor excede una regla comercial de 100.
Me pregunto si es posible en algunos idiomas definir estas reglas como anotaciones o atributos de una variable / propiedad.
Por ejemplo, en C#
usted podría escribir:
[Range(0,100)]
public int Price { get; set; }
O tal vez en C++
ti podrías escribir:
int(0,100) x = 0;
Nunca he visto algo así, pero dado lo dependientes que nos hemos vuelto de la validación de datos antes del almacenamiento. Es extraño que esta característica no se haya agregado a los idiomas.
¿Puedes dar ejemplos de idiomas donde esto sea posible?
java
c#
c++
annotations
attributes
Reactgular
fuente
fuente
data Bool = True | False
y por lo que quiere, podría decir quedata Cents = 0 | 1 | 2 | ...
tiene un mire "Tipos de datos algebraicos" (que deberían denominarse más correctamente tipos hindley-milner, pero la gente lo confunde con la inferencia de tipos de manera molesta) es.wikipedia.org/wiki/Algebraic_data_typetype
palabra clave en Pascal después de todo. La orientación a objetos es más un patrón de diseño que una propiedad "atomar" de los lenguajes de programación.Respuestas:
Pascal tenía tipos de subrango, es decir, disminuía el número de números que encajaban en una variable.
Ada también tiene una noción de rangos: http://en.wikibooks.org/wiki/Ada_Programming/Types/range
De Wikipedia ...
también puede hacer
Y aquí es donde se pone genial
C no tiene un tipo de subrango estricto, pero hay formas de imitar uno (al menos limitado) mediante el uso de campos de bits para minimizar el número de bits utilizados.
struct {int a : 10;} my_subrange_var;}
. Esto puede funcionar como un límite superior para contenido variable (en general, diría: no use bitfields para esto , esto es solo para probar un punto).Muchas soluciones para tipos enteros de longitud arbitraria en otros lenguajes suceden a nivel de biblioteca, es decir, C ++ permite soluciones basadas en plantillas.
Hay lenguajes que permiten monitorear estados variables y conectar aserciones. Por ejemplo en Clojurescript
La función
mytest
se llama cuandoa
ha cambiado (víareset!
oswap!
) verifica si se cumplen las condiciones. Este podría ser un ejemplo para implementar el comportamiento de subrango en lenguajes de enlace tardío (consulte http://blog.fogus.me/2011/09/23/clojurescript-watchers-and-validators/ ).fuente
for y in Year_Type loop ...
eliminan problemas como desbordamientos de búfer.Ada también es un lenguaje que permite límites para tipos simples, de hecho, en Ada es una buena práctica definir sus propios tipos para su programa para garantizar la corrección.
El Departamento de Defensa lo usó durante mucho tiempo, tal vez todavía lo sea, pero he perdido la noción de su uso actual.
fuente
Ver Limitar el rango de tipos de valor en C ++ para ver ejemplos de cómo crear un tipo de valor de rango verificado en C ++.
Resumen Ejecutivo: use una plantilla para crear un tipo de valor que tenga valores mínimos y máximos integrados, que puede usar de esta manera:
Realmente ni siquiera necesitas una plantilla aquí; podrías usar una clase con un efecto similar. El uso de una plantilla le permite especificar el tipo subyacente. Además, es importante tener en cuenta que el tipo de
percent
arriba no será unfloat
, sino una instancia de la plantilla. Es posible que esto no satisfaga el aspecto de "tipos simples" de su pregunta.Los tipos simples son solo eso, simples. A menudo se usan mejor como bloques de construcción para crear las herramientas que necesita en lugar de usarse directamente.
fuente
Según mi conocimiento, alguna forma restringida de su intención es posible en Java y C # a través de una combinación de Anotaciones y Patrón de proxy dinámico (existen implementaciones incorporadas para proxys dinámicos en Java y C #).
Versión Java
La anotación:
La clase Wrapper que crea la instancia de Proxy:
El InvocationHandler sirve como bypass en cada llamada a método:
La interfaz de ejemplo para el uso:
Método principal:
Salida:
Versión C #
La anotación (en C # llamado atributo):
La subclase DynamicObject:
La clase de ejemplo:
Uso:
En conclusión, ve que puede hacer que algo así funcione en Java , pero no es del todo conveniente, porque
Las capacidades de la clase DynamicObject en C # eliminan la restricción de la interfaz, como puede ver en la implementación de C #. Desafortunadamente, este comportamiento dinámico elimina la seguridad de tipo estático en este caso, por lo que las verificaciones de tiempo de ejecución son necesarias para determinar si se permite una llamada al método en el proxy dinámico.
Si esas restricciones son aceptables para usted, ¡esto puede servir como base para una mayor excavación!
fuente
public virtual int Min { get; private set; }
es un buen truco que acortaría significativamente tu códigoLos rangos son un caso especial de invariantes. De Wikipedia:
Un rango
[a, b]
puede declararse como una variable x de tipoInteger
con las invariantes x> = a y x <= b .Por lo tanto, los tipos de subrango Ada o Pascal no son estrictamente necesarios. Podrían implementarse con un tipo entero con invariantes.
fuente
No se necesitan características especiales para tipos de rango limitado en C ++ y otros lenguajes con sistemas de tipos potentes.
En C ++, sus objetivos se pueden cumplir de manera relativamente simple con tipos definidos por el usuario . Y en aplicaciones donde los tipos de rango limitado son deseables, apenas son suficientes . Por ejemplo, uno también querría que el compilador verifique que los cálculos de la unidad física se escribieron correctamente, de modo que la velocidad / tiempo produzca una aceleración, y tomar la raíz cuadrada de aceleración / tiempo produzca una velocidad. Hacer esto convenientemente requiere la capacidad de definir un sistema de tipos, sin nombrar explícitamente cada tipo que pueda aparecer en una fórmula. Esto se puede hacer en C ++ .
fuente