I guess it is not possible to invoke methods implemented in Scala traits from Java, or is there a way?
Suppose I have in Scala:
trait Trait {
def bar = {}
}
and in Java if I use it as
class Foo implements Trait {
}
Java complains that Trait is not abstract and does not override abstract method bar() in Trait
Answer
From Java perspective
Trait.scala
is compiled intoTrait
interface. Hence implementingTrait
in Java is interpreted as implementing an interface - which makes your error messages obvious. Short answer: you can't take advantage of trait implementations in Java, because this would enable multiple inheritance in Java (!)How is it implemented in Scala?
Long answer: so how does it work in Scala? Looking at the generated bytecode/classes one can find the following code:
Trait
is an interfaceTrait$class
(do not confuse withTrait.class
) class is created transparently, which technically does not implementTrait
interface. However it does have astatic bar()
method takingTrait
instance as argument (sort ofthis
)Foo
implementsTrait
interfacescalac
automatically implementsTrait
methods by delegating toTrait$class
. This essentially means callingTrait$class.bar(this)
.Note that
Trait$class
is neither a member ofFoo
, nor doesFoo
extend it. It simply delegates to it by passingthis
.Mixing in multiple traits
To continue the digression on how Scala works... That being said it is easy to imagine how mixing in multiple traits works underneath:
translates to:
Multiple traits overriding same method
Now it's easy to imagine how mixing in multiple traits overriding same method:
Again
Trait1
andTrait2
will become interfaces extendingTrait
. Now ifTrait2
comes last when definingFoo
:you'll get:
However switching
Trait1
andTrait2
(makingTrait1
to be last) will result in:Stackable modifications
Now consider how traits as stackable modifications work. Imagine having a really useful class Foo:
which you want to enrich with some new functionality using traits:
Here is the new 'Foo' on steroids:
It translates to:
Trait1
Trait2
FooOnSteroids
So the whole stack invocations are as follows:
And the result is "Foo, Trait1, Trait2".
Conclusion
If you've managed to read everything, an answer to the original question is in the first four lines...
It's indeed not abstract since
bar
is returning an emptyUnit
(a kind of NOP). Try:Then
bar
will be a Java abstract method returningvoid
.