Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cannot implicitly cast A[T] to AT, where A[T] extends AT

The problem is related to integration between Java and Scala. I have simplified it a little bit to make things clearer.

I have two classes written in Java:

class A<T>{}

class AT extends A<Boolean> {}

In Java I have a method that uses the classes in the following way:

public  A<Boolean> a(){
    return new AT();
}

I would like to do the same thing in scala. But the code below doesn't compile.

def a(): A[Boolean] = {
    return new AT();
}

The message says: "type mismatch; found : org.rarry.sample.AT required: org.rarry.sample.A[Boolean]"

Can anybody explain why it is so, and how to go about that?

like image 241
rarry Avatar asked Apr 08 '13 11:04

rarry


1 Answers

To understand the reason your code doesn't compile, first note that Java uses java.lang.Boolean for the boxed boolean type, and Scala uses scala.Boolean. Most of the time, when you want to use one of them, and a method returns the other one (or a method argument requires the other one), an implicit conversion will be performed, and the correct type will be used.

The method a that you wrote in Scala really returns A[java.lang.Boolean]. Because there's no implicit conversion between A[java.lang.Boolean] and A[scala.Boolean], it will not automatically return A[scala.Boolean] in this case.

To verify that this is the case, we can see that this method compiles without issues:

def a: A[java.lang.Boolean] = new AT()

To reiterate the point, because we don't have the implicit conversion, this will also not work (you'll see how that can be fixed below):

val instanceOfA: A[Boolean] = a
def a = new AT()
// Error: AT doesn't conform to A[Boolean] 

To fix it, you could implicitly convert to the needed type by casting it:

implicit def toScalaABoolean(a: A[java.lang.Boolean]): A[Boolean] =
        a.asInstanceOf[A[Boolean]]

With that done, you don't even have to declare the return type of a method anymore:

implicit def toDifferentBoolean(a: A[java.lang.Boolean]): A[Boolean] = 
     a.asInstanceOf[A[Boolean]]
val instanceOfA: A[Boolean] = a
def a = new AT()
like image 92
Alex Yarmula Avatar answered Oct 05 '22 23:10

Alex Yarmula