斯卡拉。泛型类声明麻烦

Posted

技术标签:

【中文标题】斯卡拉。泛型类声明麻烦【英文标题】:Scala. Generic class declaration trouble 【发布时间】:2016-02-23 19:02:49 【问题描述】:

我在 Scala 中的类声明有问题:

   class Class2[
      A,
      B <: Class2[A,B,C],
      C <: Class3[A,C]
   ]


   class Class3[
      A,
      C <: Class3[A,C]
   ]

   class Class1[
      A, 
      B <: Class2[A,B,C], 
      C <: Class3[A,C]
    ](obj : B)  ... 

这是正确的声明,但每次我想创建该类的实例时,我都需要手动指定参数 A 和 C。喜欢:

val X = Class1[Type1, Type2, Type3](correct_object_of_Type2)

如果我尝试val X = Class1(OBJ) 会导致错误...types [Nothing, B, Nothing] do not conform to [A, B, C]...

为什么 Scala 不从 B 推断类型 A 和 C?以及如何为 Scala 编译器声明类,以便它能够自己指定 A、C?谢谢

编辑

对不起,最初的任务是正确定义 Class1,如:

   class Class2[
      A,
      B <: Class2[A,B,C],
      C <: Class3[A,C]
   ]


   class Class3[
      A,
      C <: Class2[A,C]
   ]

   ??class Class1(obj : Class2)  ... ??

...所以调用val x = Class1(obj) 是正确的,其中obj: Class2。当我尝试如上所述定义它时,我收到错误Class2 takes type parameters。有什么想法吗?

抱歉不准确。

【问题讨论】:

【参考方案1】:

可以通过将约束编码为隐式参数来推断类型参数:

class Class2[X, Y, Z]
class Class3[X, y]

class Class1[A, B, C](obj: B)(implicit
  evB: B <:< Class2[A, B, C],
  evC: C <:< Class3[A, C]
)

然后:

scala> class Foo extends Class3[String, Foo]
defined class Foo

scala> class Bar extends Class2[String, Bar, Foo]
defined class Bar

scala> new Class1(new Bar)
res0: Class1[String,Bar,Foo] = Class1@ff5b51f

如果您需要在Class1 的定义中使用BC 的实例作为Class2[A, B, C]Class3[A, C],您可以应用适当的证据参数(evBevC)来他们。

您的版本不起作用,因为 Scala 的类型推断系统非常有限。它将首先解决A 并最终解决Nothing,因为构造函数的参数中没有A。接下来它将尝试解决B 并且无法找到满足约束的值,因为它已经确定ANothing

因此,您必须决定类型推断是否值得增加一点复杂性和运行时开销。有时是这样,但根据我的经验,当你有这样的类并且关系已经相当复杂时,通常不是。

【讨论】:

感谢您的回答,它有效!但我明白我并没有写出所有麻烦的细节。对不起。请检查“编辑”

以上是关于斯卡拉。泛型类声明麻烦的主要内容,如果未能解决你的问题,请参考以下文章

Java 泛型泛型用法 ( 泛型类用法 | 泛型方法用法 | 泛型通配符 ? | 泛型安全检查 )

《C#零基础入门之百识百例》(八十一)泛型概念介绍 -- 泛型类/结构/接口/委托

Java泛型知识总结篇

Java泛型类

Java 泛型方法泛型类通配符通配符上下限

泛型类