2012-07-24 54 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