Usage of @specialized in traits
Asked Answered
B

1

6

I have a trait and an implementation looking like:

trait Foo[A] {
  def bar[B >: A: Ordering]: Foo[B]
}
class FooImpl[A]( val a: A, val values: List[Foo[A]] ) extends Foo[A] {
  def bar[B >: A] = { /* concrete implementation */}
}  

I would like to use the @specialized annotation on A and B to avoid autoboxing. Do I need to use it in both trait and implementation, only in implementation, or only in trait ?

Busman answered 17/4, 2012 at 15:58 Comment(6)
How do you expect specialization to work if you're using a List which is not itself specialized? You can't avoid boxing then.Hibernal
Sorry, mistake in simplifying the code for posting. The class contains an instance of A (that I don't want to autobox, and a List[Foo[A]].Busman
Okay, but Ordering isn't specialized either.Hibernal
@RexKerr does that mean that if I rely on a non-specialized typeclass, I cannot use specialization ?Busman
If you use the typeclass, you cannot; any interactions with that typeclass will box. In your case, you will probably want to use < or the like, and that will cause boxing.Hibernal
@RexKerr I removed the context bound since it's not directly related to my question.Busman
D
3

The REPL has the right answer for us, together with javap, which will show the disassembled java code. If you add tools.jar to your REPL classpath, you will be able to do cool things like the following:

scala>  trait Foo[@specialized(Int) A] { def doSomething(a:A)}
defined trait Foo

scala>  :javap -p Foo
Compiled from "<console>"
public interface Foo{
    public abstract void doSomething(java.lang.Object);
    public abstract void doSomething$mcI$sp(int);
}

scala> class Hello extends Foo[Int] { def doSomething(a:Int)=println(a)}
defined class Hello

scala>  :javap -p Hello
Compiled from "<console>"
public class Hello extends java.lang.Object implements Foo$mcI$sp,scala.ScalaObject{
    public void doSomething(int);
    public void doSomething$mcI$sp(int);
    public void doSomething(java.lang.Object);
    public Hello();
}

So now it should be clear to you that providing the @specialized only at trait level is enough: in the Foo interface you clearly have two method declaration. It looks to me that a trick is going on there, however:

scala>  new Hello
res0: Hello = Hello@7a80747

scala>  res0.doSomething("test")
<console>:11: error: type mismatch;
 found   : java.lang.String("test")
 required: Int

While I can answer your question, there are some questions which I can't answer:

  • Why the methods are defined as public abstract in the trait?
  • Why the method doSomething(java.lang.Object) is there in the disassembled class, but cannot be called?
Di answered 17/4, 2012 at 15:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.