2013-03-19 35 views
6

Jestem zdezorientowany przez tego opisu w „5.1.3 niejawnego rozdzielczości” w książce Joshua Suareth Scala w głębi, na stronie 100:implicits dla obiektów w Scala

Scala obiekty nie mogą mieć towarzysz dla obiektów implicits. Z tego powodu, implicite związane z typem obiektu, które są pożądane w , niejawny zakres typu obiektu musi być dostarczony z zewnętrznego zakresu . Oto przykład:

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 

Ale gdy robię obiektem Bar ukryte w REPL:

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

Wydaje się, że nie ma potrzeby, aby zdefiniować niejawna w zakresie zewnętrznej. Czy mogę całkowicie odrzucić znaczenie Joshua?

+1

Kiedy została napisana książka i której wersji Scali używasz? Mogło to nieco zmienić się w 2.9 lub 2.10. – KChaloux

+1

Rzeczy są jak w mojej odpowiedzi przynajmniej od 2.9.x na. Josh musiał odnosić się do Scala przed 2.9 lub po prostu nie był świadomy semantyki. FTR Byłem zaskoczony i zachwycony, gdy odkryłem, że to jest możliwe. –

+0

Dzięki za odpowiedź. W tej książce zasugerowano, że obejmuje ona od 2.7.x do 2.9.x. Mam zainstalowany 2.10 na moim komputerze, który może zachowywać się inaczej. – cfchou

Odpowiedz

8

W tym scenariuszu obiektów działać tak, jakby były ich własnymi towarzyszami, więc wystarczy gniazdo Twój obiekt typu-wspomnieć implicits w ciele samego obiektu,

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

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

Zauważ, że tutaj korpus z Bar została uznana za część domyślnego zakresu do rozwiązania Bar.type.

Może to wyglądać na niejasny zakątek systemu typu Scala, ale udało mi się go dobrze wykorzystać w kodowaniu shapeless kodu polymorphic (function) values.

2

Jeśli umieścisz poniższy kod w pliku i spróbuj skompilować za pomocą scalac zawiedzie z 'implicit' modifier cannot be used for top-level objects

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

To jednak kompiluje grzywny:

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

wierzę pomocą REPLimplicit's są niezupełnie na najwyższym poziomie, stąd pozorna niekonsekwencja.