2012-07-24 52 views
3

我在Java代碼中定義如下:使用從Scala代碼的Java定義的遞歸一般類型

一個抽象的接口定義(由具體的端口類類型):

package test; 

public class Port< 
    PortOptions extends Port.Options, 
    ConcretePort extends Port<PortOptions, ConcretePort>> { 

    public interface Options { 
    } 

} 

的端口服務定義(可以通過一些回調機制做一些東西與端口)

package test; 

import java.util.Set; 

public class PortService { 
    public interface Callback<T> { 
     void processData(T data); 
    } 

    public void methodWithCallback(Callback<Set<Port>> callback) { 

    } 
} 

,我想一個回調註冊到從一階港口服務。我的嘗試是這樣的:

package test 

import test.PortService.Callback 
import java.util 

class PortServiceCaller { 

    def callingMethod() { 
     val portService: PortService = new PortService 

     portService.methodWithCallback(new Callback[java.util.Set[Port[_, _]]] { 
      def processData(data: util.Set[Port[_, _]]) { 

      } 
     }) 
    } 
} 

,並與悲慘的失敗:

error: type mismatch; 
found : java.lang.Object with test.PortService.Callback[java.util.Set[test.Port[_, _]]] 
required: test.PortService.Callback[java.util.Set[test.Port[_ <: test.Port.Options, _ <: test.Port[?0,?1]]]] 
portService.methodWithCallback(new Callback[java.util.Set[Port[_, _]]] { 

的問題是:如何寫Scala代碼爲了讓我正確地調用Java服務?

我已經看了scala打字系統,我似乎無法弄清楚。

後來編輯:

的方案實際上很簡單:

聲明回調方法爲:

public void methodWithCallback(Callback<Set<Port<?, ?>>> callback) { 

    } 

和階這樣稱呼它:

portService.methodWithCallback(new Callback[java.util.Set[Port[_, _]]] { 
     def processData(data: java.util.Set[Port[_, _]]) { 
     } 
    }) 

也有道理給予兩種語言的類型系統。

回答

3

你在Java中做什麼是危險的,你的代碼只能編譯,因爲Java編譯器很懶,不會檢查它。當你寫:

public void methodWithCallback(Callback<Set<Port>> callback) { 

    } 

你基本上是扔掉所有類型的信息有關端口:

Port<PortOptions extends Port.Options, ConcretePort extends Port<PortOptions, ConcretePort>> 

整個信息不會可用,Java編譯器讓你忽略類型參數。在scala中這是不可能的,不僅需要正確表達類型參數,而且還要正確表示類型約束。這裏的第一個問題就是爲什麼你寫Port的時候,甚至沒有說那裏有一些未知的類型。

public void methodWithCallback(Callback<Set<Port<?,?>>> callback) { 

} 

將是正確的寫作方式。

如果現在你想表達多種未知類型之間的邊界關係,你不能使用緊湊_對於存在類型,適用於簡單的界限,但你必須forSome

class Port[A,B<:A] 

    def myMethod(a:Port[A,B]forSome {type B; type B<:A}) 

使用,但是,作爲我傾向於說,最終使用這些模式會導致您的設計很薄弱,並且您可能會有更清晰和更優雅的方式來解決您的問題。如果您需要拋棄關於類型安全的信息,那麼使用泛型的意義何在?

+0

啊..我總是忘記參數化類型與參數化類型不同。感謝那。我能用這個解決它。 – 2012-07-24 14:00:35