首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >两个耦合的Scala泛型构造函数如何将彼此称为类型参数?

两个耦合的Scala泛型构造函数如何将彼此称为类型参数?
EN

Stack Overflow用户
提问于 2011-04-07 11:15:54
回答 2查看 739关注 0票数 4

在Java 1.6.0_21中,下面的第一个示例编译得很好,我认为这是因为参数类型边界是空的。也就是说,在下面绑定的"Z扩展Zen“中,Java允许Zen作为原始的、非泛型类型的名称(相当于运行时”擦除“类型)。这可能是错误和糟糕的,但它也可能是有用的,或至少是古怪的好时光乘公共汽车回家:

代码语言:javascript
复制
public class CorefTest {

    public static interface Tao<Z extends Zen> {
    }

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

在Scala2.8.0.final中,下面的代码通过CleanOceanWithFish进行了很好的编译,显示了一些基本类型的param连接。但是,当我们到达禅和道是相互依赖的泛型类型时,Scala编译器拒绝我的编织结构。请参阅注释中的编译器错误。

代码语言:javascript
复制
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]]]

那么,我如何才能恰当地把道与禅之间的Scala (2.8.0)结绑起来呢?

这当然是一个精心设计的例子,但我真正想要的是使用Scala来扩展我在上述表单中使用的一些实际Java类型(到目前为止,通过"forSome“和"_”的存在类型并不能帮助我)。我认为在Scala中获得Zen和Tao编译可能会为Java扩展指明方向。如果您可以在回答中考虑Java扩展问题,那就更好了。谢谢你的帮助!

Update在尼基塔S.和克里斯N.

我经验性地了解了更多关于各种Java+Scala共同引用场景的知识。其结果是,当我们想要Java和Scala中的可互操作的协同引用类型时,那么这个Java构造:

代码语言:javascript
复制
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示例更具体的类型(避免原始类型),然后在Scala中正确地扩展如下:

代码语言:javascript
复制
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中的“扩展”)和Scala中的"_ <:“的位置。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-04-07 15:14:38

因为禅宗和道都不是共变的,所以你的禅宗和道有一个可替代的问题。在2.8.1项下,这对我来说很好:

代码语言:javascript
复制
trait Tao[+Z <: Zen[Tao[Z]]]

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

当然,如果你想冥想Z或T,那么这也不适用于你,至少不完全像你所说的那样,因为在对立面上有一个协变参数。你可以这样解决这个问题:

代码语言:javascript
复制
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的答案更新中提到的问题。这可以很好地编译:

代码语言:javascript
复制
class Zazen extends Zen[Tao[Zazen]]
票数 3
EN

Stack Overflow用户

发布于 2011-04-07 11:40:07

我想,这就是你需要的

代码语言:javascript
复制
class MyClass {

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

}

这个片段由Scala2.8.1成功编译

更新

不幸的是,在scala中扩展CorefTest.ZenCorefTest.Tao是不可能的。这就是为什么。

java中实现接口的唯一方法是使用原始类型。

代码语言:javascript
复制
public class TaoImpl<Z extends CorefTest.Zen> implements CorefTest.Tao<Z> { }

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

而不是像这样实例化类:

代码语言:javascript
复制
TaoImpl<ZenImpl> tao = new TaoImpl<ZenImpl>();
ZenImpl<TaoImpl> zen = new ZenImpl<TaoImpl>();

但是scala不支持原始类型。因此,TaoImplZenImpl是无法定义的。请参阅本电子邮件线程#2091#1737的详细讨论

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5580158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档