2013-06-20 65 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

相關問題