Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement Java interface in Scala, with generics, and return null

Tags:

java

scala

I have a Java interface that looks roughly like this:

public interface Foo {
  public <T> T bar();
}

I want to implement this interface in Scala, where all of my code uses Option. However, since the interface will be used by Java users, I want to return null instead of None. I tried the following:

class FooImpl extends Foo {
  def bar[T](): T = {
    val barOpt: Option[T] = getBar()
    barOpt.orNull
  }
}

This results in the following compile error:

Expression of type Null does not conform to expected type T

This makes sense, type T is unrestricted, it could be an Int or some other type that can't be null. No problem, just add T >: Null and you're done, right?

class FooImpl extends Foo {
  def bar[T >: Null](): T = {
    val barOpt: Option[T] = getBar()
    barOpt.orNull
  }
}    

Nope, still no dice. Now you get a new compile error:

[error]  method bar has incompatible type

It seems that you can't apply any restrictions to T and still implement that interface.

Next, I tried using asInstanceOf:

class FooImpl extends Foo {
  def bar[](): T = {
    val barOpt: Option[T] = getBar()
    barOpt.orNull.asInstanceOf[T]
  }
}    

But that just gets one more error:

Cannot prove that Null <:< T.

Is there any way to make this work?

like image 569
Yevgeniy Brikman Avatar asked Mar 26 '26 10:03

Yevgeniy Brikman


1 Answers

You could use getOrElse and cast to T:

scala> def test[T](t: T): T = { Option(t).getOrElse(null).asInstanceOf[T] }
test: [T](t: T)T

You could move ugly stuff to helper class:

implicit class Defaults[T](val o: Option[T]) extends AnyVal {
  def orDefault(): T = o.getOrElse(null).asInstanceOf[T]
}

def test[T](t: T): T = { Option(t).orDefault }
like image 148
senia Avatar answered Mar 28 '26 00:03

senia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!