2012-07-30 65 views
7

我想實現一個在scala(2.9.2)中使用泛型的java方法。但我沒有......Scala,不能實現通用java方法

Java接口方法:

public <T extends Number> void setAttribute(Key<T> key, Number value); 
希望實施該方法

Scala代碼:

def setAttribute[T <: Number](key: Key[T], value: Number) = { 
    setAttributeLocal(key, value) } 

private def setAttributeLocal[T](key: Key[T], value: T) = { 
    val stringValue = ConvertUtils.convert(value, classOf[String]).asInstanceOf[String] 
    session = session + (key.getValue() -> stringValue) 
} 

主要的樣子:

public class Key<T> 

但是這不能編譯。

[error] found : mypackage.Key[T] 
[error] required: mypackage.Key[java.lang.Number] 
[error] Note: T <: java.lang.Number, but Java-defined class Key is invariant in type T. 
[error] You may wish to investigate a wildcard type such as `_ <: java.lang.Number`. (SLS 3.2.10) 
[error]  setAttributeLocal(key, value) 

我找不出什麼問題。任何建議/想法?

greez GarfieldKlon

+1

我們需要知道'Key'的樣子。因爲如果我使用'public interface Key ',上面的代碼編譯得很好。 – 2012-07-30 14:24:21

+0

@GarfieldKlon你正在使用哪個版本的scala? – 2012-07-30 14:34:54

+0

@ 0__在哪個版本下編譯? – 2012-07-30 14:35:52

回答

4

它出現的編譯器是不滿您的來電setAttributeLocalsetAttributeLocal需要Key[Number],但您提供了Key[_ <: T]。在Java-Land中,這意味着您試圖將Key<? extends Number>作爲Key<Number>關閉。

建議讓setAttributeLocal接受Key<? extends Number>Key[_ <: Number],這取決於它是Java或Scala定義的。

+0

@GarfieldKlon我不得不閱讀幾遍......我認爲Ben的建議是,如果你專注於修復'setAttribute',那麼你可能會看到錯誤的東西。你描述的錯誤是'setLocalAttribute'類型問題,而不是'setAttribute'。你對'setLocalAttribute'的定義是什麼樣的? – 2012-07-30 14:39:02

+0

@理查德 - 好吧,這就解釋了爲什麼我不能重現這 – 2012-07-30 14:46:51

+0

我們最後添加了這個解決方案:'private def setAttributeLocal [T](key:Key [T],value:Object)' – GarfieldKlon 2012-11-02 12:25:21

1

東西看起來有點偏離這裏。

你試過:

def setAttribute[T <: Number](key: Key[T], value: T) = 
    setAttributeLocal(key, value) 

這似乎很奇怪/壞保存爲重點類型T,但不使用它的價值。我的猜測是那裏你得到一個不變的錯誤。您試圖將Number類型的值分配給T類型的密鑰,編譯器不確定它是否無法通過Number代替T(雖然它知道它可以通過代替Number)。

我們能看到更多的代碼嗎?

+0

這不是一個選項,因爲它不是一個覆蓋。 – GarfieldKlon 2012-08-02 07:20:28

+0

Java和Scala的類型接口有一些限制。你在Java中做什麼是不健全的,所以Scala不允許它。 如果你想繼續使用這種類型巫術,那麼你必須堅持使用Java的類型系統,對不起。 – jsuereth 2012-08-02 11:05:48

1

正如@jsuereth已經指出的那樣,是setAttributesetAttributeLocal,即簽名之間的差異,前者接受Key[T <: Number]但修復與關鍵到底出是Number價值,而後者是更靈活,並允許關鍵和價值爲T <: Number。這看起來很奇怪,你可能想重新考慮這個決定。這也導致了@Ben Schulz解釋的問題。在任何情況下,編譯器(2.9.2)1)是滿意以下設置:

MyI.java

public interface MyI { 
    public <T extends Number> void setAttribute(Key<T> key, Number value); 
} 

Key.java

public interface Key<T> { 
} 

Test.scala

object Test extends App { 
    def setAttribute[T <: Number](key: Key[T], value: Number) = { 
    setAttributeLocal(key, value) } 

    private def setAttributeLocal[T](key: Key[T], value: Number) = { 
    /* Notice that value is now also of type Number. */ 
    } 
}