2010-05-13 8 views
6

Recientemente empecé a notar una repetición en algunos de mis códigos. Por supuesto, una vez que notas una repetición, se vuelve irritante. Por eso estoy haciendo esta pregunta.¿Hay un término para este concepto, y existe en un lenguaje de tipo estático?

La idea es esta: a veces escribes diferentes versiones de la misma clase: una versión sin formato, una versión bloqueada, una versión de fachada de solo lectura, etc. Estas son cosas comunes que hacer a una clase, pero las traducciones son muy mecánico. Rodee todos los métodos con lock acquire/releases, etc. En un lenguaje dinámico, podría escribir una función que hiciera esto en una instancia de una clase (por ejemplo, iterar sobre todas las funciones, reemplazándolas por una versión que adquiera/libere un bloquear.).

Creo que un buen término para lo que quiero decir es 'clase reflejada'. Crea una transformación que toma una clase y devuelve una clase modificada en una ruta deseada. La sincronización es el caso más fácil, pero hay otros: hacer una clase inmutable [ajustar los métodos para que clonen, muten el clon, y lo incluyan en el resultado], hagan una clase de solo lectura [suponiendo que puedan identificar métodos de mutación], hagan una clase parece que funciona con tipo A en lugar de tipo B, etc.

La parte importante es que, en teoría, estas transformaciones tienen sentido en tiempo de compilación. Aunque un ActorModel <T> tiene métodos que cambian en función de T, dependen de T de una manera específica cognoscible en tiempo de compilación (ActorModel <T> métodos devolverían un futuro del tipo de resultado original).

Me pregunto si esto se ha implementado en un idioma y cómo se llama.

Respuesta

2

Si entiendo bien, usted le gustaría ser capaz de generar nueva clase/tipo a través de una transformación de un tipo existente. Algo así como

class Synchronized<T> { 
    Object invocation(Object ... args) { 
     synchronize(this) { 
      return original.invocation(args); 
     } 
    } 
} 
... 
Foo f; 
Synchronized<Foo> f2; 
f.bar(); 
f2.bar(); // would be valid for the type-system 

, donde invocation y original sería palabras clave para esta nueva abstracción.

El nuevo tipo se puede ver como un proxy de /envoltorio/adaptador alrededor del tipo original. Si el nuevo tipo todavía representa un subtipo del original o no es otra pregunta. Hasta qué punto la abstracción apoyaría el cambio del tipo de devolución también es otra cuestión.

Si bien la instrumentación del código de bytes, el AOP o el cargador de clases personalizado podría lograr parte de esto, diría que en espíritu, la coincidencia más cercana es un proxy dinámico. El código de un proxy dinámico parece realmente terrible similar a lo que escribí arriba. Here, here y here son situaciones que he resuelto con proxies dinámicos. Por supuesto, los proxies dinámicos no son estáticos, sino como su nombre lo dice, dinámico.

Me temo que el problema general que describe, cómo crear variaciones de tipos existentes, es demasiado amplio. La proposición de la extensión del sistema de tipo se ha realizado para situaciones específicas, p. cómo crear un adaptador de la interfaz X a Y para que toda la implementación concreta de X también pueda verse como la implementación de Y.

Tal vez echar un vistazo a estos documentos (no he leído todos ellos todavía, pero planeo):

Por último, el resumen dice:

Se discuten las ventajas precisas y costos de nuestra extensión en términos de los criterios introducidos, e ilustramos la utilidad de manera uniforme disponibles proxies implementando el método futuro invocaciones de forma segura y de forma transparente.

, que era una de sus preguntas.

Pregunta fresca por cierto, deseo que exista una solución general a su problema. No pretendo ser un experto en el tema, por lo que podría haber uno, pero no estoy al tanto.

1
+0

Sin duda suena similar, y cubre algunos de los casos. Pero, usando aspectos, ¿puedo tomar una clase y hacer que los métodos devuelvan futuros en lugar de los valores normales? –

+0

Normalmente, no se puede cambiar el tipo de devolución con AOP, un poco el punto es que el código que lo usa desconoce los aspectos. –

0

¿No podría hacer esto con las plantillas? Sería poco hacker, sino algo así como:

#define LOCKED = true; 
#define UNLOCKED = false; 

template<bool lock> 
void doStuff(){ 
    if(lock){ 
     // get lock 
    } 
    // other code 
    if(lock){ 
     // release lock 
    } 
} 
+0

No lo sé. Nunca exploré los límites de las plantillas de C++. ¿Pueden crear una clase cuyos métodos se basan en los métodos de una subclase? –

+0

¿Podría crear una instancia de su subclase como una variable miembro y luego usar sus métodos? O si son funciones estáticas, puede usarlas como 'SubclassName :: functionName()' –

0

Python tiene decorators que están relacionados con lo que está hablando.

+0

Creo que los decoradores se aplican a la definición, no a la creación de instancias, de las clases. Además, pregunté específicamente sobre el caso estático, porque los lenguajes dinámicos hacen que estas transformaciones sean relativamente fáciles. –

+0

@Strilanc: Leo tu pregunta más rápido de lo que debería. Pero los decoradores son solo funciones que se aplican a las clases, y en principio se puede decorar una clase y crear instancias de un objeto localmente. –

Cuestiones relacionadas