Scala 为什么抽象类型的具体实现不能用于推断类标记?
考虑到以下准则:Scala 为什么抽象类型的具体实现不能用于推断类标记?,scala,typeclass,abstract-type,Scala,Typeclass,Abstract Type,考虑到以下准则: object DelayedClassTagInference { trait SS { type TT <: Any implicit val ctg: ClassTag[TT] = implicitly[ClassTag[TT]] val fakeCtg: ClassTag[None.type] = implicitly[ClassTag[None.type]] } class Sub1 extends SS {
object DelayedClassTagInference {
trait SS {
type TT <: Any
implicit val ctg: ClassTag[TT] = implicitly[ClassTag[TT]]
val fakeCtg: ClassTag[None.type] = implicitly[ClassTag[None.type]]
}
class Sub1 extends SS {
override final type TT = Int
}
class Sub2 extends SS {
override final type TT = Double
}
class Sub3 extends SS {
override final type TT = String
}
}
class DelayedClassTagInference extends FunSpec {
import DelayedClassTagInference._
it("") {
val sub1 = new Sub1()
println(sub1.fakeCtg)
println(sub1.ctg)
}
}
所以ctg的值是null,除了触发NullPointerException之外,这也没有意义。它是一个scala包,以后应该修复吗?删除
valctg
的implicit
修饰符,您将看到您的代码没有编译。您不应该手动定义隐式ClassTag
/TypeTag
/WeakTypeTag
,它们应该在类型已知时由编译器自动生成
实际上,当您隐式调用ClassTag[TT]]
时,会使用您现在定义的隐式val ctg:ClassTag[TT]
,这就是为什么它在运行时为null
隐式在编译时解析,当调用sub1.ctg
时,解析调用哪个.ctg
发生在运行时(这就是子类型多态性的工作方式)。在编译时还不知道它是Sub1#ctg
替换
implicit val ctg: ClassTag[TT] = implicitly[ClassTag[TT]]
与
我知道,在运行时您将使用
Int
而不是null
,但是Sub1和Sub2也在编译时解析,它们的方法签名应该根据编译时的情况进行调整,只有val Sub1
的静态类型已知,它的运行时类型未知(无论它是Sub1
的某个特定子类型,.ctg
都可以在那里重写)。Sub1
现在没有子类,但这与此无关。不确切地说,是一个精确的抽象类型(定义为=,而不是:)无论是否声明为final,都无法重写。因此,此时可以确定类标记。有关证据,请参阅本文:我不是在谈论类型成员,我是在谈论方法成员。.ctg
是一个方法。它可以被重写。在编译时,中的.ctg
是未知的ub1.ctg
是Sub1
的.ctg
@tribbloid Replaceimplicit-val-ctg:ClassTag[TT]=隐式[ClassTag[TT]]
与def-ctg(implicit-tag:ClassTag[TT]):ClassTag[TT]=隐式[ClassTag[TT].
一起使用Int
而不是null
。
implicit val ctg: ClassTag[TT] = implicitly[ClassTag[TT]]
def ctg(implicit tag: ClassTag[TT]): ClassTag[TT] = implicitly[ClassTag[TT]]