2015-09-06 16 views
5

sto guardando questa forma uno sfondo Objective-C in modo da essere gentile. L'esperimento sembra questo:Pharo Smalltalk - Come posso verificare se un messaggio è conforme a un protocollo definito nella classe di un altro oggetto?

Object1 ha una variabile di istanza denominata delegato.

L'oggetto 1 riceve un messaggio e il ricavato per verificare se il delegato implementa un protocollo specifico (il cui nome è noto in precedenza), se lo fa, verifica se il messaggio è tra i metodi implementati del protocollo. Prende quindi una decisione su come interagire con il delegato e così via.

In Objective-C si deve definire protocolli chiari, generalmente memorizzati in file differenti, e conforme al protocollo è controllato dal compilatore. In Pharo non riesco a trovare il modo di verificare questo tipo di informazioni anche se il browser ha un'intera colonna dedicata ai protocolli e, a parte i metodi di raggruppamento, sembra che facciano molto poco.

+1

Non conosco molto dei "protocolli" in Objective-C, ma hai ragione, in Smalltalk non sono molto più di un modo per raggruppare i metodi (a.k.a. "categorie"). Ci sono convenzioni su come definire questi protocolli e quali metodi tipicamente vanno in quale protocollo, ma sono solo, bene, convenzioni. Puoi chiedere a una classe di '#allMethodsInCategory:', ma a meno che non ti fraintenda, non penso che sia quello che cerchi, perché sembra che siano qualcosa di completamente diverso in Objective-C. La risposta di Leandro offre alcune opzioni per verificare a quali metodi risponde un oggetto. –

+1

@ AmosM.Carpenter Era esattamente quello che stavo cercando, l'ho trovato io stesso mentre cercavo qualcos'altro. C'era un metodo #allMethodsInCategory: che è stato deprecato in Pharo 3.0 e successivamente in favore di #allSelectorsInProtocol: che fa quello che voglio. Vedi http://stackoverflow.com/questions/2990966/how-can-i-get-all-the-methods-in-a-protocol Alcuni altri dialetti hanno metodiInProtocol: tutti uguali. – unmircea

risposta

5

Ecco alcuni poche alternative che potrebbero aiutare con questo:

  1. ottenere l'insieme di tutti i selettori che popolano la classe dell'oggetto:
    • anObject class selectors
  2. ottenere l'insieme di tutti i selettori che popolano la classe dell'oggetto e tutte le sue superclassi:
    • anObject class allSelectors
  3. Chiedi alla classe se si implementa un dato messaggio (per le sue istanze):
    • anObject class canUnderstand: #putTheSelectorHere
  4. Chiedi l'oggetto se si capisce un dato messaggio:
    • anObject respondsTo: #methodSelectorHere
  5. Utilizzare il MessageNotUnderstood meccanismo:
    • (vedi spiegazione sotto)

In 1 e 2 è possibile utilizzare le collezioni restituiti per verificare se essi comprendono un certo selettore di sei interessato. Le caratteristiche 3, 4 e 5 hanno una natura più dinamica. Ad esempio, è possibile perfezionare il metodo #doesNotUnderstand: nella classe come segue:

MyClass >> #doesNotUnderstand: aMessage 
    (delegate respondsTo: aMessage selector) 
     ifTrue: [^delegate 
      perform: aMessage selector 
      withArguments: aMessage arguments]. 
    ^super doesNotUnderstand: aMessage 

In questo modo, se l'oggetto riceve un messaggio che non comprende, in primo luogo ricevere il messaggio #doesNotUnderstand: (senza dover fare qualsiasi cosa per questo accada) e qui potresti decidere (es, usando il messaggio #respondsTo:) se delegarlo o meno. In caso contrario, è possibile inoltrare il comportamento predefinito (super doesNotUnderstand:) che segnalerebbe l'eccezione di MessageNotUnderstood.

Naturalmente, c'è una sesta opzione, che sarebbe per il mittente del messaggio per gestire l'eccezione MNU, ma non penso che questo sia quello che stai cercando qui.

+0

Da quello che vedo: #doesNotUnderstand viene chiamato dopo che non è stato possibile trovare un metodo per il selettore. Pertanto, con ogni messaggio otterrei il sovraccarico di questo messaggio e non potrò inoltrare i selettori di oggetti di base, poiché sia ​​il redirector che il delegato sono Oggetti e il redirector inoltrerà solo se non lo comprende. Objective-C ha forwardInvocation: che inoltra assolutamente tutto anche prima che la ricerca del metodo abbia luogo. Ce l'abbiamo in Smalltalk? – unmircea

+2

vedi Ghost and papers –

+0

@unmircea Probabilmente ho frainteso la tua domanda. Forse potresti modificarlo per aiutarci a capire meglio cosa stai cercando di fare. –

3

I proxy funzionano in Ghost/Marea e nell'originale Smalltalk wrappers to the rescue Non sono sicuro che i proxy siano stati aggiornati per l'ultima versione di Pharo. Ultima versione fantasma sembra essere here

+0

Grazie per la risposta rapida ... Stavo cercando qualcosa di più diretto come Obj-C [[myObject class] conformsToProtocol: @protocol (MyProtocol)]; che sarebbe supportato immediatamente, qualcosa sulla falsariga della classe myObject conformsToProtocol: 'Whatever'. – unmircea