2010-05-13 8 views
6

Recentemente ho iniziato a notare una ripetizione in alcuni dei miei codici. Certo, una volta che si nota una ripetizione, diventa una grata. È per questo che sto facendo questa domanda.Esiste un termine per questo concetto e esiste in un linguaggio tipizzato staticamente?

L'idea è questa: a volte si scrivono versioni diverse della stessa classe: una versione grezza, una versione bloccata, una versione di facciata di sola lettura, ecc. Queste sono cose comuni da fare a una classe, ma le traduzioni sono altamente meccanico. Circondare tutti i metodi con il lock acquisisce/rilascia, ecc. In un linguaggio dinamico, è possibile scrivere una funzione che ha fatto ciò a un'istanza di una classe (ad esempio, iterare su tutte le funzioni, sostituendole con una versione che acquisisce/rilascia un serratura.).

Penso che un termine valido per ciò che intendo sia "classe riflessa". Crei una trasformazione che accetta una classe e restituisce una classe modificata in una maniera desiderata. La sincronizzazione è il caso più semplice, ma ce ne sono altri: rendere una classe immutabile [metodi di avvolgimento in modo da clonare, mutare il clone e includerlo nel risultato], creare una classe in modo readonly [presumendo che sia possibile identificare i metodi mutanti], creare una classe sembra funzionare con il tipo A invece che con il tipo B, ecc.

La parte importante è che, in teoria, queste trasformazioni hanno senso in fase di compilazione. Anche se un ActorModel T > ha metodi che cambiano a seconda di T, essi dipendono da T in un modo specifico conoscibile in fase di compilazione (ActorModel <T> metodi restituirebbe un futuro del tipo di risultato originale).

Mi chiedo se questo è stato implementato in una lingua e come si chiama.

risposta

2

Se ho capito bene, si vorrebbe essere in grado di generare nuova classe/tipo attraverso una trasformazione di un tipo esistente. Qualcosa di simile

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 

, dove invocation e original sarebbe parole chiave per questa nuova astrazione.

Il nuovo tipo può essere visto come un procura/involucro/adattatore tutto il tipo di originale. Se il nuovo tipo rappresenta ancora un sottotipo dell'originale o meno è quindi un'altra domanda. Quanto l'astrazione supporterebbe la modifica del tipo di ritorno è anche un'altra domanda.

Mentre strumentazione bytecode, AOP o class loader personalizzato potrebbero realizzare parte di questo, direi che nello spirito della corrispondenza più vicina è un proxy dinamico. Il codice di un proxy dinamico sembra davvero terribile simile a quello che ho scritto sopra. Here, here e here sono situazioni che ho risolto con i proxy dinamici. Ovviamente i proxy dinamici non sono statici ma come dice il nome, dinamico.

temo che il problema generale che si descrive - come creare variazioni di tipi esistenti - è troppo ampia. Proposte di estensione del sistema di tipo sono state fatte per situazioni specifiche, ad es. come creare un adattatore da un'interfaccia X a Y in modo che tutti concreta attuazione di X può anche essere visto come realizzazione di Y.

Forse uno sguardo a questi documenti (non ho letto tutti loro ancora, ma ho intenzione di):

Per l'ultimo, l'abstract dice:

Discutiamo i benefici precisi e costi della nostra estensione in termini di criteri introdotti, e illustrare l'utilità di uniformemente disponibili proxy implementando in modo trasparente le chiamate successive al metodo in modo sicuro e con in modo trasparente.

, che era uno della sua domanda.

Cool question btw, Vorrei che esistesse una soluzione generale al tuo problema. Non pretendo di essere un esperto in materia, quindi potrebbe essercene anche uno, ma non ne sono consapevole.

1
+0

Sembra certamente simile e copre alcuni dei casi. Ma, usando gli aspetti, posso prendere una lezione e i metodi restituiscono i futures anziché i valori normali? –

+0

In genere, non è possibile modificare il tipo di ritorno con AOP, un po 'il punto è che il codice che lo utilizza non è a conoscenza degli aspetti. –

0

Non potresti farlo con i modelli? Sarebbe un po 'hacker, ma qualcosa di simile:

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

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

Non lo so. Non ho mai esplorato i limiti dei modelli C++. Possono creare una classe i cui metodi sono basati su metodi di una sottoclasse? –

+0

È possibile creare un'istanza della sottoclasse come variabile membro e quindi utilizzarne i metodi? O se sono funzioni statiche, puoi usarle come 'SubclassName :: functionName()' –

0

Python ha decorators correlati a ciò di cui si sta parlando.

+0

Penso che i decoratori si applichino alla definizione, non all'istanziazione, delle classi. Inoltre, ho chiesto espressamente il caso statico, perché i linguaggi dinamici rendono queste trasformazioni relativamente facili. –

+0

@Strilanc: Ho letto la tua domanda più velocemente di quanto avrei dovuto. Ma i decoratori sono solo funzioni che si applicano alle classi e in linea di principio puoi decorare una classe e istanziare un oggetto localmente. –