0

我有一个关于在 Scala 中定义方法/类时何时使用类型参数化与基类类型的问题,特别是当允许的类型在同一层次结构中时 - 使用类型绑定进行约束。

例如:

trait TypeA
case class SubTypeA1(in: String) extends TypeA
case class SubTypeA2(in: String) extends TypeA

case class NewType[T <: TypeA](inTypeA: T) 
case class NewTypeV2(inTypeA: TypeA) 

def testMethod1(in: String): NewType[TypeA] = NewType(SubTypeA1(in))
def testMethod2(in: NewType[TypeA]): Unit = print("Some functionality")
def testMethod3(in: String): NewTypeV2 = NewTypeV2(SubTypeA1(in))
def testMethod4(in: NewTypeV2): Unit = print("Some functionality")

在上述情况下/通常当将允许的类型限制在某个上限时,我会获得什么优势,NewType反之亦然NewTypeV2?他们看起来都和我一样。

据我了解,如果我要添加一些隐式条件检查,例如NewType[T: Addable]存在于不同层次结构的类型中,那么类型参数化将是有意义的,除了我应该更喜欢类型参数化而不是使用接口类型或基类类型(如案例类成员inTypeA的类型。NewTypeV2

像 NewType[T] 这样定义类型参数化的方式是否被认为比其他方式更“功能性”?

其次,关于方差与类型界限的问题。在上面的代码块中,NewType 在 Type T 上是不变的,所以 NewType[SubTypeA1] 不是 NewType[TypeA] 的子类型,它们是不相关的,对吗?

如果如上所述我对类型不变性的理解是正确的,那么 testMethod1 是如何编译的?因为我明确地传递了 SubTypeA1 但它仍然被转换为 NewType[TypeA] 并且它可以毫无问题地传递给 testMethod2 。我在这里有什么误解?

scala> testMethod1("test")
res0: NewType[TypeA] = NewType(SubTypeA1(test))

scala> testMethod2(testMethod1("test"))
Some functionality

scala> NewType(SubTypeA1("tst"))
res3: NewType[SubTypeA1] = NewType(SubTypeA1(tst))
4

1 回答 1

1
case class NewType[T <: TypeA](inTypeA: T) 
case class NewTypeV2(inTypeA: TypeA) 

这两者之间的区别是类型inTypeA

NewTypetype of 中inTypeA是类型参数T,可以是 的任何子类型TypeA。编译器知道实际的子类型是什么。

NewTypeV2类型inTypeATypeA。该值将是 的子类型TypeA,但编译器只知道它是TypeA

如果您有一个需要特定子类型的方法,这很重要TypeA

def subtypeMethod(in: SubTypeA1) = ???

val a1 = SubTypeA1("string")

val n = NewType(a1)
subtypeMethod(n.inTypeA) // Yes, inTypeA is type SubTypeA1

val n2 = NewTypeV2(a1)
subtypeMethod(n2.inTypeA) //No, inTypeA is type TypeA
于 2020-09-16T07:28:53.963 回答