斯卡拉。 Generic class 声明麻烦
Scala. Generic class declaration trouble
我在 Scala 中的 class 声明有问题:
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) { ... }
这是正确的声明,但每次我想创建它的实例时 class 我需要手动指定参数 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 编译器声明 class 以便它能够自己指定 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
。有什么想法吗?
抱歉不准确。
可以通过将约束编码为隐式参数来推断类型参数:
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
的定义中使用 B
或 C
的实例作为 Class2[A, B, C]
或 Class3[A, C]
,您可以应用适当的给他们的证据参数(evB
或 evC
)。
您的版本无法运行,因为 Scala 的类型推断系统非常有限。它将首先求解 A
并以 Nothing
结束,因为构造函数的参数中没有 A
。接下来它将尝试解决 B
并且无法找到满足约束的值,因为它已经确定 A
是 Nothing
.
所以你必须决定类型推断是否值得额外的复杂性和运行时开销。有时是这样,但根据我的经验,当你有 类 这样的关系已经相当复杂时,通常不会。
我在 Scala 中的 class 声明有问题:
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) { ... }
这是正确的声明,但每次我想创建它的实例时 class 我需要手动指定参数 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 编译器声明 class 以便它能够自己指定 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
。有什么想法吗?
抱歉不准确。
可以通过将约束编码为隐式参数来推断类型参数:
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
的定义中使用 B
或 C
的实例作为 Class2[A, B, C]
或 Class3[A, C]
,您可以应用适当的给他们的证据参数(evB
或 evC
)。
您的版本无法运行,因为 Scala 的类型推断系统非常有限。它将首先求解 A
并以 Nothing
结束,因为构造函数的参数中没有 A
。接下来它将尝试解决 B
并且无法找到满足约束的值,因为它已经确定 A
是 Nothing
.
所以你必须决定类型推断是否值得额外的复杂性和运行时开销。有时是这样,但根据我的经验,当你有 类 这样的关系已经相当复杂时,通常不会。