斯卡拉.通用类声明问题

y.k*_*aev 3 scala generic-programming user-defined-functions

我在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) { ... }
Run Code Online (Sandbox Code Playgroud)

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

val X = Class1[Type1, Type2, Type3](correct_object_of_Type2)
Run Code Online (Sandbox Code Playgroud)

如果我尝试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) { ... }??
Run Code Online (Sandbox Code Playgroud)

......所以打电话是正确的val x = Class1(obj),在哪里obj: Class2.当我尝试如上定义它时,我收到错误Class2 takes type parameters.有任何想法吗?

抱歉,不准确.

Tra*_*own 6

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

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]
)
Run Code Online (Sandbox Code Playgroud)

然后:

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
Run Code Online (Sandbox Code Playgroud)

如果你需要使用的情况下,BC作为Class2[A, B, C]Class3[A, C]在定义中Class1,可以将相应的证据参数(申请evBevC)给他们.

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

因此,您必须确定类型推断是否值得额外的复杂性和运行时开销.有时它是,但根据我的经验,当你有这样的课程时,关系已经相当复杂,通常不是.