类型参数化,方差与继承基类的用法

问题描述

当在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))

解决方法

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

这两者之间的区别在于inTypeA的类型:

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

NewTypeV2中,inTypeA的类型为TypeA。该值将是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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...