2011-04-07 44 views
4

在Java 1.6.0_21中,下面的第一个例子编译得很好,我认为这是因为参数类型边界是空的。也就是说,在下面的“Z extends Zen”范围内,Java允许将Zen作为非原始类型的原始名称(相当于运行时“删除” 类型)。这可能是错误的,坏的,但它也可能是有用的,或坐大巴回家至少古怪 美好的时光:两个耦合的Scala泛型类型构造函数如何相互引用类型参数?

public class CorefTest { 

    public static interface Tao<Z extends Zen> { 
    } 

    public static interface Zen<T extends Tao> { 
    } 
} 

在斯卡拉2.8.0.final,下面通过CleanOceanWithFish编译伟大了,显示 一些基本类型参​​数连接。但是当我们认识到Zen和Tao是相互依赖的泛型类型时,Scala编译器会拒绝我的编织结构。查看注释中的编译器错误。

package heaven.piece 
class Lucky { 
    trait Water {} 
    trait CleanWater extends Water {} 
    trait Sea [W <: Water] {} 
    trait Fish[S <: Sea[CleanWater]] {} 

    trait CleanOceanWithFish[F <: Fish[CleanOceanWithFish[F]]] 
        extends Sea[CleanWater]{} 

// Above code compiles fine, but the type constructor pair below doesn't compile 

    trait Tao[Z <: Zen[Tao[Z]]]{}; 

    trait Zen[T <: Tao[Zen[T]]]{}; 
} 
// error: type arguments [Lucky.this.Tao[Z]] do not conform to trait Zen's 
//  type parameter bounds [T <: Lucky.this.Tao[Lucky.this.Zen[T]]] 

// error: type arguments [Lucky.this.Zen[T]] do not conform to trait Tao's 
//  type parameter bounds [Z <: Lucky.this.Zen[Lucky.this.Tao[Z]]] 

那么,怎样才能正确地我绑斯卡拉(2.8.0)结道与禅之间?我真正想要的是使用Scala来扩展一些真正的Java类型,我使用上面的形式(通过“forSome”和“[_]”存在的类型并不能帮助你我到目前为止)。我认为在Scala中编译Zen和Tao 可能会显示出Java扩展的方式。如果你可以在你的答案中考虑Java扩展问题,那么更好。谢谢你的帮助!从尼基塔S.和克里斯N.很有帮助前两个回答以下问题,

我经验学到了一些更多关于各种Java +斯卡拉的共参照情景后

更新公布。其结果是,当我们想在互操作coreferent类型都的Java和Scala,那么这个Java结构:

public static interface JavaFunTao<JFZ extends JavaFunZen<? extends JavaFunTao<JFZ>>> { 
    public JFZ consider(JFZ someZen, JavaFunTao<JFZ> otherTao); 
} 
public static interface JavaFunZen<JFT extends JavaFunTao<? extends JavaFunZen<JFT>>> { 
    public JFT meditate(JFT someTao, JavaFunZen<JFT> otherZen); 
} 

提供在顶部更具体的打字比我的第一个Java例子(避免原始类型),并且是然后在斯卡拉正确扩展如下:

class HiFunTao[HFZ <: HiFunZen[ _ <: HiFunTao [HFZ]]] extends JavaFunTao[ HFZ] { 
    override def consider(someZen: HFZ, otherTao: JavaFunTao[HFZ]) : HFZ = { 
     println (this.toString() + " is considering " + someZen + " and " + otherTao); 
     someZen 
    } 
} 
class HiFunZen[HFT <: HiFunTao[ _ <: HiFunZen [HFT]]] extends JavaFunZen[ HFT] { 
    override def meditate(someTao: HFT, otherZen: JavaFunZen[HFT]) : HFT = { 
     println (this.toString() + " is meditating on " + someTao + " and " + otherZen); 
     someTao 
    } 
} 

我证实,我们可以根据这些简单的具体类型,实例化它们,并调用它们的方法。 Java和Scala中的关键步骤是将有界通配符放在类型参数树循环回当前声明类型的位置,即java中的“?extends”和Scala中的“_ <:”。

回答

3

因为无论是禅,也不是道协,还有在禅和道一个可替代性的问题。这在2.8.1编译为我好:

trait Tao[+Z <: Zen[Tao[Z]]] 

trait Zen[+T <: Tao[Zen[T]]] 

当然,如果你想在z或T打坐那么这也不会为你工作,至少不完全是因为这个问题的声明在逆变位置具有协变类型参数。让您可以像这样的问题:

trait Tao[+Z <: Zen[Tao[Z]]] { 
    def meditate[M >: Z](m: M) =() 
} 

trait Zen[+T <: Tao[Zen[T]]] { 
    def meditate[M >: T](m: M) =() 
} 

但这仍可能产生,你可能不希望在你执行的因素。至少这是令人困惑的。 :)

更新:

这也,顺便说一下,避免NSkvortsov的答案的更新中提到的问题。这编译罚款:

class Zazen extends Zen[Tao[Zazen]] 
+0

伟大的解决方案!没想到的协方差可以帮助) – 2011-04-07 16:06:46

+0

是克里斯Nuttycombe,你的有关协变原来的答复是一大 帮助!我想,我现在明白了 斯卡拉性状可替代性问题,为什么协方差注解修复它。您的笔记 方法反转也是有帮助的。你所有的代码都可以在2.8.1上从我这里编译 。 在你的更新中,你是否在说你认为Java类型实际上应该可以从Scala扩展,使用Zazen技术(这对我来说还不适用)?或者你是否同意NSkvortsov的更新:由于原始类型问题,扩展在Scala中的java类型是不可能的? – 2011-04-07 22:32:10

+0

糟糕,我错过了NSkvortsov正在谈论扩展Java的Scala。我确信扩展Java类型的问题是可以解决的,因为我必须先做一次,但现在我似乎无法弄清楚如何使它工作。 :P – 2011-04-08 03:49:33

2

我想,这是你所需要的:

class MyClass { 

    trait Tao[Z <: Zen[_]]{}; 
    trait Zen[T <: Tao[_]]{}; 

} 

这个片段成功斯卡拉2.8.1

更新编译

不幸的是,在斯卡拉扩展CorefTest.ZenCorefTest.Tao是不可能的。这是为什么。

以实现的Java接口的唯一方法是使用原始类型

public class TaoImpl<Z extends CorefTest.Zen> implements CorefTest.Tao<Z> { } 

public class ZenImpl<T extends CorefTest.Tao> implements CorefTest.Zen<T> { } 

不是一个可以实例化这样的类:

TaoImpl<ZenImpl> tao = new TaoImpl<ZenImpl>(); 
ZenImpl<TaoImpl> zen = new ZenImpl<TaoImpl>(); 

斯卡拉做不支持原始类型。所以TaoImplZenImpl就是不能定义的。 请参阅本e-mail thread和问题#2091#1737进行详细讨论

+0

谢谢你,是的,这在2.8.0编译。所以我尝试添加一个使用Z到你的陶的方法: } 和我得到一个编译器OutOfMemory错误,表明从编译器递归深入挖掘我的类型提示原始查询的同类欲望。 – 2011-04-07 12:00:07

+0

很奇怪。我试着添加一个方法,同时检查2.8.0和2.8.1脚本和编译模式 - 一切正常。这里是道码:'特质道[Z <:Zen [_]] {def meditate(z:Z):Unit = {println(“meditating on”+ z); }};' – 2011-04-07 12:37:45

+0

再次感谢NSkvortsov!我更新到Scala 2.8.1。现在“冥想”方法编译。好吧,所以我认为这是一种体面的方式,可以获得与我们在Java中具有的相同功能(马虎)。 然而,我原来真正的问题(在我的问题的底部暗示)是未解,因为[_]技术不工作,在斯卡拉扩大共同指称通用的Java类型。我可能会提出这个问题作为一个单独的问题,但同时有人可以说出我的原始一对更加紧密编织的Scala类型构造函数是非法的,它仍然在2.8.1下给出相同的错误? Спасибоotra vez! – 2011-04-07 13:06:47

相关问题