2013-06-20 63 views
2

我有一个Java界面,看起来大致是这样的:实现Scala的Java接口,使用泛型,并返回null

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

我想要实现在Scala中,所有的我的代码使用Option这个接口。但是,由于该接口将被Java用户使用,因此我想返回null而不是None。我试过如下:

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

这将导致以下编译错误:

Expression of type Null does not conform to expected type T 

这是有道理的,类型T是不受限制的,它可能是一个Int或一些其他类型的,可以不null。没问题,只需加上T >: Null就完成了,对吗?

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

不,还没有骰子。现在,你会得到一个新的编译错误:

[error] method bar has incompatible type 

看来你不能施加任何限制T,仍然实现该接口。

接下来,我尝试使用asInstanceOf

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

但是,这只是变得多了一个错误:

Cannot prove that Null <:< T. 

有什么办法,使这项工作?

+0

[尝试此处(HTTP://计算器。com/questions/10065962/how-to-a-function-in-scala) – BevynQ

+0

@BevynQ:正如我在描述中写的,我尝试的第一件事是'T>:Null',但这会导致第二个错误。 –

+0

我不知道scala,但它支持这种构造吗? 'barOpt。 orNull'? – fge

回答

6

你可以使用getOrElse和转换为T

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

你可以丑陋的东西转移到辅助类:

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 } 
+0

这确实有用,但是......该死的就是那个丑陋的。 –

+0

我知道,但'T'可能是'AnyVal'。你可以隐藏投射看到更新。 – senia

0

我怀疑@塞尼亚的回答将被证明是可用的最佳选择纯粹的斯卡拉。如果没有新的东西出现,我会将其标记为“官方”答案。

为了完整起见,这里是使用Java类来封装这个肮脏的交易,给它一个明确的名称的解决办法,而且,同样重要的是,说明为什么它的存在:

public class JavaOptionHelper { 
    // http://stackoverflow.com/questions/17205142/implement-java-interface-in-scala-with-generics-and-return-null 
    public static <T> T toValueOrNull(Option<T> option) { 
    if (option.isDefined()) { 
     return option.get(); 
    } else { 
     return null; 
    } 
    } 
} 

它可以作为如下:

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

以下为我工作:

scala> def test[T >: Null] = null 
test: [T >: Null]=> Null 

scala> test[String] 
res18: Null = null 

scala> def test2[T](x : T)(implicit ev: Null <:< T) = x 
test2: [T](x: T)(implicit ev: <:<[Null,T])T 

scala> test2("Hallo") 
res19: java.lang.String = Hallo 

scala> test2(null) 
res20: Null = null 

还有为e关于StackOverflow的讨论涵盖了相当不错的主题。详情请参阅here

相关问题