2009-12-16 5 views
17

Se voglio aggiungere un metodo a una classe in Scala, ho bisogno di fare qualcosa di simile:Capire perché "pimp my library" è stata definita in questo modo in Scala

class RichFoo(f: Foo) { 
    def newMethod = f.bar() 
} 
object RichFoo { 
    implicit def foo2Rich(f: Foo) = new RichFoo(f) 
} 

Poi f.newMethod si tradurrà nella creazione di RichFoo e chiama il suo metodo.

sto cercando di capire il motivo per cui non è stato definito in modo simile a Ruby:

override class Foo { 
    def newMethod = bar 
} 

Il compilatore può guardare questa definizione, e creare una classe FooOverride con metodo newMethod statico che riceve un parametro di tipo Foo e chiama il suo metodo bar. Questo è il modo in cui Scala implementa i tratti. Devo ancora importare il pacchetto che contiene l'override di Foo per usarlo.

Sembra implicare meno digitazione, non richiede di inventare nomi e prestazioni migliori (non chiamare un metodo e creare un oggetto). Qualunque cosa il metodo di conversione implicito può fare all'interno del metodo aggiuntivo.

Sono sicuro di aver perso qualcosa e vorrei avere un'idea di cosa.

+0

non rubino davvero fuori eseguire Scala in questo caso, o stai speculando che un'implementazione open class può essere fatto veloce come un chiuso? –

+3

Suggerisco una facciata che sembra stia riaprendo una classe, ma in realtà chiama solo metodi statici. Lo scala compilatore fa sempre cose del genere (i tratti sono compilati in un'interfaccia e una classe con metodi statici). Suppongo che sia meno codificante e più veloce rispetto all'attuale modo implicito di defs – IttayD

risposta

13

Ci sono altri usi per le conversioni implicite diverse da solo l'idioma "pimp my library", quindi non è davvero un caso di "perché non hanno fatto questo invece?", ma "perché non lo hanno fatto anche loro?". Certamente, non vedo alcun motivo per cui una sintassi dei metodi di estensione non possa essere aggiunta come suggerisci e probabilmente sarebbe un po 'più pulita, ma non c'è bisogno di farla, visto che il linguaggio supporta già un modo per ottenere lo stesso effetto .

Aggiornamento Ottobre 2011:

C'è una nuova proposta di aggiungere lo zucchero sintassi per questo caso d'uso: http://scala.github.com/sips/pending/implicit-classes.html

+0

Immagino che tu abbia ragione. – IttayD

+1

La tua risposta è corretta. Volevo sottolineare che in effetti esiste un'estensione sperimentale del compilatore Scala (chiamato Scala-virtualizzato) che supporta l'aggiunta di metodi a classi esistenti scrivendo meno codice - cerca "def infix_ +" in questa classe per trovare alcuni esempi : https://github.com/TiarkRompf/virtualization-lms-core/blob/e11ee5c5c9eb5d00e38927f5f1722bc956e8615d/src/ppl/StringOps.scala supporti Scala-virtualizzati anche altre caratteristiche, per i quali il miglior riferimento (anche se incompleta) è questo : https://github.com/tiarkrompf/scala-virtualized/wiki – Blaisorblade

8

Come si impedisce a tale metodo di accedere all'ambito senza richiedere un'importazione esplicita e dandogli un nome? In effetti, come può un programma sapere quali metodi sono stati aggiunti senza farlo?

Quando si utilizzano tre diverse librerie, due delle quali aggiungono metodi al terzo in un modo incompatibile, come si potrebbe aggirare questo senza avere impliciti sotto controllo?

A parte ciò, non è possibile ottenere prestazioni migliori, poiché la JVM non consente di modificare una classe esistente. Nella migliore delle ipotesi, potresti ottenere il vantaggio di non dover inventare un nome e dover digitare meno a costo di non essere in grado di controllare ciò che viene fatto.

Come nota finale, se si vuole insomma, si può fare:

implicit def fooBar(f: Foo) = new { def newMethod = bar } 
+2

Importare invece l'override di Foo. Non ho suggerito di cambiare classe. Ho suggerito che foo.bar sarà convertito in com.my.package.Foo.bar (foo). Il tuo ultimo esempio significa chiamare newMethod tramite reflection – IttayD

+4

Il 'new {...} 'thing è un tipo strutturale. Stai attento a questo: i suoi metodi sono chiamati via riflessione, il che lo rende lento. Vedi http://stackoverflow.com/questions/3119580/scala-equivalent-of-csharps-extension-methods/3119671#3119671 – Jesper

Problemi correlati