2013-03-19 17 views
6

Sono confuso da questa descrizione in "5.1.3 risoluzione implicito" nel libro di Joshua Suareth Scala in profondità, a pagina 100:impliciti per gli oggetti in Scala

Scala oggetti non possono avere gli oggetti compagno per impliciti. A causa di questo, impliciti associati al tipo dell'oggetto, che sono desiderati su l'ambito implicito del tipo di quell'oggetto, devono essere forniti da un ambito esterno . Ecco un esempio:

scala> object Foo { 
    | object Bar { override def toString = "Bar" } 
    | implicit def b : Bar.type = Bar 
    |} 
defined module Foo 
scala> implicitly[Foo.Bar.type] 
res1: Foo.Bar.type = Bar 

Ma mentre io faccio oggetto Bar implicita REPL:

scala> object Foo { 
    | implicit object Bar { 
    |  override def toString = "isBar" } 
    | } 
defined module Foo 
scala> implicitly[Foo.Bar.type] 
res0: Foo.Bar.type = isBar 

Sembra che non ha bisogno di definire un implicito nel perimetro esterno. O prendo il significato di Joshua completamente sbagliato?

+1

Quando è stato scritto il libro e quale versione di Scala stai usando? Questo potrebbe essere cambiato un po 'in 2.9 o 2.10. – KChaloux

+1

Le cose sono come nella mia risposta almeno dal 2.9.x in poi. Josh doveva essere riferito a Scala pre-2.9, o semplicemente inconsapevole della semantica. FTR Sono rimasto sorpreso e felice quando ho scoperto che era possibile. –

+0

Grazie per la risposta. È suggerito in questo libro che copre da 2.7.x a 2.9.x. Ho installato 2.10 sulla mia macchina che potrebbe comportarsi diversamente. – cfchou

risposta

8

In questo scenario gli oggetti si comportano come se fossero i propri compagni, quindi è sufficiente nido l'oggetto-tipo-menzionare impliciti nel corpo dell'oggetto stesso,

scala> object Bar { 
    | override def toString = "Bar" 
    | implicit def b : Bar.type = Bar 
    | } 
defined module Bar 

scala> implicitly[Bar.type] 
res0: Bar.type = Bar 

Si noti che qui il corpo di Bar è stato considerato come parte dell'ambito implicito per la risoluzione di Bar.type.

Questo potrebbe sembrare un angolo oscuro del sistema di tipi di Scala, ma sono stato in grado di utilizzarlo nella codifica shapeless di polymorphic (function) values.

2

Se si inserisce il seguente codice in un file e tenta di compilare usando scalac fallisce con un 'implicit' modifier cannot be used for top-level objects

implicit object Foo { 
    object Bar { override def toString = "Bar" } 
} 

Questo però compila bene:

object Foo { 
    implicit object Bar { override def toString = "Bar" } 
} 

Credo utilizzando il REPLimplicit's sono non esattamente di primo livello quindi l'apparente incongruenza.

Problemi correlati