score:137
Answer
From Java perspective Trait.scala
is compiled into Trait
interface. Hence implementing Trait
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:
interface Trait {
void bar();
}
abstract class Trait$class {
public static void bar(Trait thiz) {/*trait implementation*/}
}
class Foo implements Trait {
public void bar() {
Trait$class.bar(this); //works because `this` implements Trait
}
}
Trait
is an interface- abstract
Trait$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 of Foo
, nor does Foo
extend it. It simply delegates to it by passing this
.
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:
trait Trait1 {def ping(){}};
trait Trait2 {def pong(){}};
class Foo extends Trait1 with Trait2
translates to:
class Foo implements Trait1, Trait2 {
public void ping() {
Trait1$class.ping(this); //works because `this` implements Trait1
}
public void pong() {
Trait2$class.pong(this); //works because `this` implements Trait2
}
}
Multiple traits overriding same method
Now it's easy to imagine how mixing in multiple traits overriding same method:
trait Trait {def bar(){}};
trait Trait1 extends Trait {override def bar(){}};
trait Trait2 extends Trait {override def bar(){}};
Again Trait1
and Trait2
will become interfaces extending Trait
. Now if Trait2
comes last when defining Foo
:
class Foo extends Trait1 with Trait2
you'll get:
class Foo implements Trait1, Trait2 {
public void bar() {
Trait2$class.bar(this); //works because `this` implements Trait2
}
}
However switching Trait1
and Trait2
(making Trait1
to be last) will result in:
class Foo implements Trait2, Trait1 {
public void bar() {
Trait1$class.bar(this); //works because `this` implements Trait1
}
}
Stackable modifications
Now consider how traits as stackable modifications work. Imagine having a really useful class Foo:
class Foo {
def bar = "Foo"
}
which you want to enrich with some new functionality using traits:
trait Trait1 extends Foo {
abstract override def bar = super.bar + ", Trait1"
}
trait Trait2 extends Foo {
abstract override def bar = super.bar + ", Trait2"
}
Here is the new 'Foo' on steroids:
class FooOnSteroids extends Foo with Trait1 with Trait2
It translates to:
Trait1
interface Trait1 {
String Trait1$$super$bar();
String bar();
}
abstract class Trait1$class {
public static String bar(Trait1 thiz) {
// interface call Trait1$$super$bar() is possible
// since FooOnSteroids implements Trait1 (see below)
return thiz.Trait1$$super$bar() + ", Trait1";
}
}
Trait2
public interface Trait2 {
String Trait2$$super$bar();
String bar();
}
public abstract class Trait2$class {
public static String bar(Trait2 thiz) {
// interface call Trait2$$super$bar() is possible
// since FooOnSteroids implements Trait2 (see below)
return thiz.Trait2$$super$bar() + ", Trait2";
}
}
FooOnSteroids
class FooOnSteroids extends Foo implements Trait1, Trait2 {
public final String Trait1$$super$bar() {
// call superclass 'bar' method version
return Foo.bar();
}
public final String Trait2$$super$bar() {
return Trait1$class.bar(this);
}
public String bar() {
return Trait2$class.bar(this);
}
}
So the whole stack invocations are as follows:
- 'bar' method on FooOnSteroids instance (entry point);
- Trait2$class's 'bar' static method passing this as argument and returning a concatenation of 'Trait2$$super$bar()' method call and string ", Trait2";
- 'Trait2$$super$bar()' on FooOnSteroids instance which calls ...
- Trait1$class's 'bar' static method passing this as argument and returning a concatenation of 'Trait1$$super$bar()' method call and string ", Trait1";
- 'Trait1$$super$bar' on FooOnSteroids instance which calls ...
- original Foo's 'bar' method
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...
score:2
It's indeed not abstract since bar
is returning an empty Unit
(a kind of NOP). Try:
trait Trait {
def bar: Unit
}
Then bar
will be a Java abstract method returning void
.
Source: stackoverflow.com
Related Query
- Using Scala traits with implemented methods in Java
- Using a Java library with Scala reserved words
- Using Scala with Java in Android Studio
- Overriding Java interface with overloaded vargs methods in Scala
- Using scala vararg methods in java
- Implementing inner traits in Scala like we do with inner interfaces in Java
- Using Scala reflection with Java reflection
- Problems using protobufs with java and scala
- Using ListView from Scala 2.9.2 with Java 7 gives compile error
- Factory methods for implementations of Java interfaces wrapped with Scala implicits?
- How to implement Java interface in Scala with multiple variable parameter methods (type eraser issue)?
- Java or Scala fast way to parse dates with many different formats using java.time
- How to create new instance of Scala class with context bound via Java reflection using only zero argument constructor?
- Calling different methods from different traits in scala with multiple inheritance
- Building a project with mixed Scala and Java source files using Ant - illegal cyclic reference error
- Using Java annotations with Java interface implementations in Scala
- Scala traits using generics and case class methods
- Using Java generic class with raw types in Scala
- How to use java libraries with scala using sbt?
- Unable to compile spring boot project with java and scala using maven
- Compilation error with bounded wildcards using Java classes in Scala
- Delete Elasticsearch document by ID with Scala using Java API
- Error in serializing classes with traits on Scala using pickling?
- Scala: generate Java annotation with parameter using Scala macros
- Get method parameters with specific annotation in aspect in scala using java reflection
- Using Java 7 CommonDataSource with Scala
- Using Scala class in Java test with Gradle
- Type mismatch, found Unit, required Int. Using pattern matching, Scala with Java libraries
- How to call a scala function with parameters using java classloader?
- Using java classes in Play framework with Scala to be returned as Json Object
More Query from same tag
- How to use a `universe.Tree` created and type-checked in one Scala macro execution, in another macro execution?
- Spring Data with Scala
- Implementing a Scala trait by passing functions as arguments
- Boilerplate-free Scala ArrayBuilder specialization
- How to group parameterized types (classes)?
- Scala interpreter says object is not a member of package, when it is
- Scala lambda style (x) => {...} vs { (x) => ... }
- What is the difference between case object defined in scala repl and sbt console?
- How can an implicit be unimported from the Scala repl?
- How to define an empty query
- Select only specific attributes in a list[classType]?
- How to call a default function on instantiating a class object
- Appending to a list pattern matching
- "Or"-ing two Options in Scala?
- object kafka is not a member of package org.apache
- Transform one case class into another when the argument list is the same
- Cassandra SimpleStatement protected constructor
- Installing scala in windows machine
- When writing SBT tasks in build.sbt, how do I use my library dependencies?
- Error: not found: value lit/when - spark scala
- How do I get a Date to store as a Date in MongoDB instead of an Int64?
- R tm package and Spark/python give different vocabulary size for Document Term Frequency task
- Difference between case class and case object?
- How to watch remote Akka Actor?
- how do i transform a HashMap[T,Future[N]] to Future[HashMap[T,N]]
- Does it make any sense to use pattern matching in Scala with really simple cases?
- Filter after a group by in Spark
- Iterator: pairing up last element with a different value
- Scala parallel calculation and interrupt when one method returns a result
- How to figure out the functor for cats.Parallel?