How does the Scala compiler handle concrete trait methods?

Up vote 7 down vote favorite 1 share g+ share fb share tw.

If I have the following Scala class: abstract class MyOrdered extends OrderedMyOrdered { def id: Int def compare(that : MyOrdered) : Int = if (that==null) 1 else (id-that. Id) } Then I only need to define the id method in Scala to get a concrete class. But if I try to extend it in Java, the compiler says that all the concrete methods of Ordered are missing.

So, does that mean that the Scala compiler is only putting the implementation of the concrete methods of Ordered in concrete Scala classes? This seems very wasteful, because I could have dozens of concrete classes implementing MyOrdered, and they would all get a copy of the same code, when in fact it would be enough to just put it directly in the base class MyOrdered. Also, this makes it very difficult to create a Java-friendly Scala API.

Is there any way to force the Scala compiler to put the method definitions where it should have done so anyway, apart from making the class concrete by using dummy method implementations? Even funnier is declaring a concrete method final in a Scala trait. In that case, it is still not implemented in an abstract Scala class that extends the trait, but it cannot be implemented in a Java class that extends the abstract Scala class because it is flagged as final.

This is definitely a compiler bug. Final abstract methods make no sense, even if they are legal in the JVM, apparently. Java scala trait link|improve this question asked Aug 14 '11 at 13:44Sebastien Diot1,404411 79% accept rate.

Compiler bugs should be reported to issue tracker with minimal source code example showing the problem. – Grzegorz Kossakowski Aug 14 '11 at 13:54 Yes, but I don't report bugs lightly, so I was hoping to get some people to agree with me on this first. I might be mistaken, after all.

– Sebastien Diot Aug 14 '11 at 14:00 2 I'm happy to help you verify it but I don't understand the problem you are describing. Small Scala code examples + description expected behaviour would help a lot. Feel free to edit your question.

When it comes to extending traits that have some methods implemented from Java the best answer would be: don't do that. It's going to be a problem sooner or later. The reason is that Java has nothing corresponding that Scala could map onto so it does various tricks that are confusing from Java point of view.

– Grzegorz Kossakowski Aug 14 '11 at 14:45 I think the problem with the final trait method is an issue from the "presentation compiler" of Eclipse rather then Scala. And anyway since extending a trait-with-code in Java is "not supported", how the "final" is treated is in essence irrelevant. – Sebastien Diot Aug 14 '11 at 16:54.

Scala 2.9.1. RC1 Let me introduce you to our friend :javap in the REPL, which can be useful for diagnosing errors. First, we define the class, scala> abstract class MyOrdered extends OrderedMyOrdered { | def id: Int | def compare(that : MyOrdered) : Int = | if (that==null) 1 else (id-that.

Id) | } defined class MyOrdered And then ask to see the JVM bytecode, scala> :javap -v MyOrdered Compiled from "" public abstract class MyOrdered extends java.lang. Object implements scala.math. Ordered,scala.

ScalaObject ... ** I'm skipping lots of things here: $less, $lessEq, ... ** ... public boolean $greater(java.lang. Object); Code: Stack=2, Locals=2, Args_size=2 0: aload_0 1: aload_1 2: invokestatic #19; //Method scala/math/Ordered$class. $greater:(Lscala/math/Ordered;Ljava/lang/Object;)Z 5: ireturn LineNumberTable: line 7: 0 ... public abstract int id(); public int compare(MyOrdered); Code: Stack=2, Locals=2, Args_size=2 0: aload_1 1: ifnonnull 8 4: iconst_1 5: goto 17 8: aload_0 9: invokevirtual #38; //Method id:()I 12: aload_1 13: invokevirtual #38; //Method id:()I 16: isub 17: ireturn LineNumberTable: line 10: 0 ... We see that scalac actually generates methods in MyOrdered corresponding to those concrete ones in trait Ordered.

For example, the > method gets translated to $greater and basically just calls scala/math/Ordered$class. $greater. If we like, we can now look up the bytecode for concrete trait definitions, scala> :javap -v scala.math.

Ordered$class Compiled from "Ordered. Scala" public abstract class scala.math. Ordered$class extends java.lang.

Object ... public static boolean $greater(scala.math. Ordered, java.lang. Object); Code: Stack=2, Locals=2, Args_size=2 0: aload_0 1: aload_1 2: invokeinterface #12, 2; //InterfaceMethod scala/math/Ordered.

Compare:(Ljava/lang/Object;)I 7: iconst_0 8: if_icmple 15 11: iconst_1 12: goto 16 15: iconst_0 16: ireturn LineNumberTable: line 46: 0 ... Finally, let's test your hypothesis that a subclass M of MyOrdered gets a full copy of all the methods scala> class M extends MyOrdered { def id = 2 } defined class M scala> :javap -v M Compiled from "" public class M extends MyOrdered implements scala. ScalaObject .... ** No extra methods besides id ** .... Nope, it looks like there's no code duplication here. To conclude, Scalac does some magic with traits with concrete methods, so don't try to inherit from them in Java.

Abstract classes should be OK. The JVM doesn't natively support symbolic method names, Scala singleton objects, nor traits with concrete methods, so the Scala compiler needs to do some translation, and uses the reserved symbol $. If you're still having problems with Java interop, hopefully :javap will help you in diagnosing the specific problem.

1 Yes, it took me a few hours, but I came to the same conclusion. I think the problem I have is related to how scalac specifies the generic parameters in the class file. Looking at decompiled concrete scala class, I see that the "$greater" ... take a java.lang.

Object, and are simply inherited from the abstract base class which defines them. This is what we would expect. BUT javac will refuse to compile a Java class extending the abstract scala class unless it contains "$greater" ... with MyOrdered as parameter, although they are obviously neither needed, nor used.

Strange... – Sebastien Diot Aug 14 '11 at 16:50.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions