2013-11-20 2 views
9

Defined пустого черта Тест:случая ошибка генерации объекта класса компаньона для типа соединения

trait Test 

, что используется в типе соединения:

scala> val a : Int with Test = 10.asInstanceOf[Int with Test] 
a: Int with Test = 10 

и случай класс с параметром типа соединения (например, Unboxed Метки Тип):

scala> case class Foo(a: Int with Test) 
error: type mismatch; 
found : Double 
required: AnyRef 
Note: an implicit exists from scala.Double => java.lang.Double, but 
methods inherited from Object are rendered ambiguous. This is to avoid 
a blanket implicit which would convert any scala.Double to any AnyRef. 
You may wish to use a type ascription: `x: java.lang.Double`. 

Но он прекрасно работает для:

scala> case class Foo(a: List[Int] with Test) 
defined class Foo 

И никаких проблем с определением метода:

scala> def foo(a: Int with Test) = ??? 
foo: (a: Int with Test)Nothing 

Scala версия 2.10.3

Это нормальное поведение компилятора?

+7

Это [известная проблема] (https://issues.scala-lang.org/browse/SI-5183). –

ответ

5

Вы столкнулись с одним из случаев, когда попытка Scala унифицировать примитивы и объекты ломается. Поскольку Int в Scala представляет примитивный тип Java int, он не может иметь никаких черт, смешанных с ним. При выполнении asInstanceOf, компилятор Scala autoboxes Int в java.lang.Integer:

scala> val a: Int with Test = 10.asInstanceOf[Int with Test] 
a: Int with Test = 10 

scala> a.getClass 
res1: Class[_ <: Int] = class java.lang.Integer 

Однако Autoboxing не происходит при объявлении типов, так что вы должны сделать это вручную:

scala> case class Foo(x: Integer with Test) 
defined class Foo 

Но тогда тип компилятора проверки не Autobox перед проверкой типов:

scala> Foo(a) 
<console>:12: error: type mismatch; 
found : Int with Test 
required: Integer with Test 
       Foo(a) 
       ^

так вы должны объявить переменную как Integer with Test:

scala> val a: Integer with Test = 10.asInstanceOf[Integer with Test] 
a: Integer with Test = 10 

scala> Foo(a) 
res3: Foo = Foo(10) 

или использовать слепок при вызове класса случай:

val a : Int with Test = 10.asInstanceOf[Int with Test] 
scala> a: Int with Test = 10 

scala> Foo(a.asInstanceOf[Integer with Test]) 
res0: Foo = Foo(10) 
Смежные вопросы