3

Say I have the following class defined in java:

public class A
{
  public class B
  {
  }

  public B[] someFunc() {...}
}

And I am trying to access it in scala as follows:

val array: Array[A#B] = a.someFunc()

The compiler gives me the following warning:

*type mismatch; found : Array[a.B] required: Array[A#B] Note: a.B <: A#B, but class Array is invariant in type T. You may wish to investigate a wildcard type such as `_ <: A#B*

I am not sure of the correct syntax I should use to get over this error. I tried using the following but it will not compile:

val array: Array[T <: A#B] = a.someFunc()

But I have found away to get over the problem by passing it to a function:

def test[T <: A#B](array: Array[T]) = ...
test(a.someFunc())

which compiles fine.

How would I achieve the correct type assignment without having to define this test function?

Thanks

Des

1 Answer 1

1

Your B inner class is not marked static, which means, from the scala point of view, it is not a member of the companion object (i.e. a static member) A#B but it is a member of the instantiated object itself a.B.

So you should just declare your value this way:

val array: Array[a.B] = a.someFunc()

Or let type inference do it:

val array = a.someFunc() // typed as Array[a.B]

Edit: in case you do not have a reference to a lying around, usually you can just upcast a.B to A#B. Array is invariant, so that won't work, but there is a ruse: wrap it in something covariant.

val array: IndexedSeq[A#B] = a.someFunc()

You can use that one like an array, it doesn't actually convert anything (it is a WrappedArray), and you can call toArray on it if you really want to get an Array[A#B].

That is just a trick to avoid doing a.someFunc().asInstanceOf[Array[A#B]], but of course you could directly do that.

Sign up to request clarification or add additional context in comments.

3 Comments

The problem with that solution is you need a reference to a specific instance of an A object. And this is not always going to be feasible. Say I want to define a class or a function to operate on such a type when I have no such instance. As I showed in my original question there is a way to achieve what I want by defining a function. I believe we are just missing the correct syntax to do this without having to define said function.
you are right, you need an instance of A. The real problem is that path-dependent types are just compiler fiction; at runtime, everything is A#B. But there is no direct way to tell the compiler "I know what I am doing, this is safe" except, of course, a cast. See edit.
There are a few areas of Scala that are definitely cringe-worthy; this (path-dependent typing of instances of non-static inner classes) seems to be one of them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.