2013-01-07 13 views
11

Sto facendo ricerche in Reflection Smalltalk e mi chiedevo se fosse possibile estendere un singolo oggetto come sarebbe possibile ad esempio in Ruby. Con questo intendo un selettore a cui solo oggetti particolari rispondono.È possibile estendere un singolo oggetto in Smalltalk

Ecco un codice Ruby che indica cosa intendo. Per chiarimenti: in Ruby questo apre una classe virtuale per questo oggetto e la estende con una nuova definizione. La parte vitale qui è che nulla cambia nella definizione della classe!

o = Object.new 
o.instance_eval {def foo;puts "foo";end} 
o.foo #=> "foo" 

#however this will fail: 
m = Object.new 
m.foo #=> NoMethod error 

Più in particolare la mia domanda è se questo è possibile in Squeak Standard/Pharo o altre implementazioni Smalltalk, senza l'aggiunta di strutture o codice sostanziali per permettere questo. Quindi con altre parole con caratteristiche riflessive regolari che esistono in Smalltalk.

Ad esempio, è possibile aggiungere metodi, rimuovere metodi, compilare un nuovo codice in una classe, modificare variabili di istanza e qualsiasi cosa, ma non ho trovato un modo per estendere un singolo oggetto.

Test addInstVarNamed: #var. 
Test compile: 'var ^var'. 
t:= Test new. 
Test instVarNames. 
t instVarNamed: #var put: 666. 
t var. #=> 666 

Se la risposta è no, allora spiegare perché. Non sto cercando di risolvere questo problema, ma piuttosto di capire perché non si tratta di un piccolo problema.

risposta

6

In Smalltalk non esiste un modo integrato di fare un comportamento specifico dell'istanza in questo modo. Smalltalk aderisce al principio che ogni oggetto appartiene a una classe e il suo comportamento e la sua forma dipende dalla classe. Questo è il motivo per cui puoi facilmente cambiare classe (aggiungi inst vars, compila nuovi metodi, ecc.), Ma ciò significa cambiare il comportamento in tutte le sue istanze. Esistono, tuttavia, approcci diversi (secondo il gusto Smalltalk) per ottenere un comportamento specifico dell'istanza, come le classi leggere, in cui l'idea è di creare una classe speciale (leggera) per un'istanza particolare e sostituire la classe originale con quella uno personalizzato. Di conseguenza hai una classe speciale per ogni istanza "speciale". AFAIK in Digitalk St il meccanismo di dispatching è un po 'più flessibile e consente di implementare facilmente il comportamento basato su istanze (vedi 4 ° link). Lascio qui alcuni link che si possono trovare utili:

HTH

Modifica:il link pubblicato da Hernan ("Debugging Objects" di Hinkle, Jones & Johnson) è quello a cui mi riferivo e che non riuscivo a trovare.

+0

Ho già letto il primo link, ma può essere ancora difficile capire l'idea reale che c'è dietro come hai appena spiegato. Darò sicuramente un'occhiata agli altri link. Risposta eccellente – froginvasion

+0

Forse lo screencast (link 3d) ti darà una migliore comprensione. Sto cercando di trovare * la * carta che spiega in dettaglio come funzionano le classi leggere, ma non riesco a trovarlo. Dammi solo un paio di minuti :) –

+0

Siamo spiacenti, non riesco ancora a trovarlo. Ho aggiunto un quinto link con un'eccellente spiegazione su come funziona la ricerca dei metodi in Smalltalk e le diverse tecniche utilizzate per manipolare il recapito dei messaggi. Si riferisce anche all'approccio di classe leggero. –

1

In Ruby, per quanto ne so, un dizionario di metodo si collega a un oggetto.

In Smalltalk, il dizionario del metodo è associato a un oggetto Class quindi, in un'immagine Smalltalk vaniglia, non è possibile scrivere cose simili a eigenclass.

Detto questo, ci sono alcune librerie di prototipi: this question's answers ne menzionano alcune.

+0

Penso che tu abbia entrambi in Ruby in realtà. Sono anche legati all'oggetto Class, ma l'eigenclass che viene creato quando si estende un oggetto è una nuova classe separata che si estende dalla eigenclass della classe. Ma comunque, controllerò il link grazie! – froginvasion

9

Avere un comportamento specifico dell'istanza in Smalltalk consiste essenzialmente nel cambiare una classe puntatore e una chiamata primitiva. L'articolo "Debugging Objects" di Bob Hinkle, Vicki Jones e Ralph E. Johnson, pubblicato su The Smalltalk Report, Volume 2 # 9, luglio-agosto 1993, contiene tutte le spiegazioni.

Ho portato il codice originale classi leggere dalla versione rilasciata nel 1995 da Bob Hinkle per VisualWorks 2.0. L'origine di VisualWorks include il codice diviso in tre pacchetti denominati "ParameterizedCompiler", "Punto di interruzione" e "Leggero". La ragione di questa divisione è stata generata dal desiderio di avere funzionalità separate e riutilizzabili. Tutti hanno articoli separati nelle riviste OOP.

mio Squeak/Pharo port contiene un "istanze del browser", sulla base del quadro OmniBrowser (e più documentation here), che consente di sfogliare e modificare le istanze aggiungendo il comportamento leggero attraverso la classica interfaccia utente Smalltalk Browser. Funzionerebbe nelle ultime versioni di Squeak 4.x con uno sforzo minimo o nullo. Sfortunatamente l'infrastruttura di Pharo è cambiata sostanzialmente dalle versioni < = 1.2, quindi potrebbe essere necessario un po 'di lavoro per far funzionare le ultime versioni.

Instances Browser with an instance modified

In VisualWorks, a causa dei profondi cambiamenti nella GUI VisualWorks da 2,0 a 7,3, la maggior parte degli strumenti per gestire le classi leggeri non sono stati inclusi. Se qualcuno è interessato, posso caricare il pacco VW 7,3

Instances Browser in VisualWorks

Uno script di base per testare le classi leggeri caratteristiche è:

| aDate | 
aDate := Date today. 
aDate becomeLightweight. 
aDate dispatchingClass 
     compile: 'day ^42' 
     notifying: nil 
     ifFail: [self error]. 
aDate day inspect 
+0

... e quello era il documento che stavo cercando ma non ho trovato. +1! –

2

Un colleage ha lavorato una nuova API di riflessione per Pharo Smalltalk che si chiama Bifrost. puoi controllare la pagina del Bifrost project.

Il suo approccio spinge gli adattamenti specifici dell'istanza al centro. Tutto avviene legando i metaoggetti agli oggetti regolari per adattarli. I metaoggetti di livello inferiore possono essere composti in metaobiettivi di livello superiore, a grana grossa, che definiscono adattamenti sensibili, ad es. un metaobject di profilo che misurerà il tempo impiegato da ciascuna invocazione sull'oggetto target.

2

Come sottolinea @ewernli Bifrost rende in pratica Smalltalk un sistema di riflessione centrato sugli oggetti. Tutte le modifiche riflessive sono mirate prima agli oggetti invece di avere un meccanismo ibrido con le classi. Si può ancora fare tutto il riflesso della classe tradizionale, ma al di sopra della riflessione orientata agli oggetti. Quello che penso che è rilevante di questo nuovo approccio è una serie di applicazioni che abbiamo trovato che migliora il modo che abbiamo sviluppato e percepito un sistema live:

Object-centric debugging cambia completamente il nostro modo di debug concentrandosi su oggetti e permettendo allo sviluppatore di rimanere interagendo con oggetti vivi piuttosto che dover inserire breakpoint condizionali a livello di codice sorgente.

Talents sono unità dinamiche componibili di riutilizzo, come i tratti ma per gli oggetti. Ci sono molte altre applicazioni.

4

Squeak Etoys utilizza pesantemente lo stato e il comportamento specifici dell'oggetto. Questo è implementato come "uniclass". Quando crei uno script per un oggetto Etoys (istanza della classe Player), la classe dell'oggetto verrà modificata in "uniclass", ovvero una sottoclasse unica di Player, che può avere i propri metodi (corrispondenti agli script di Etoys) e variabili di istanza (corrispondenti alle variabili utente di Etoys).

Altri progetti basati su Squeak utilizzano le uniclasse "anonime", che non sono elencate come sottoclasse nella sua superclasse. Ciò significa che sono praticamente invisibili in quanto non vengono visualizzati in un System Browser, ad esempio (mentre le unilass in stile Etoys vengono visualizzate nel browser).

Problemi correlati