这很好用
class MyClass[T<: Actor: ClassTag] extends Actor {
//....
}
但这不是由于错误
No ClassTag available for MyClass.this.T
class MyClass extends Actor {
type T<: Actor
//...
}
即使执行以下操作:
class MyClass extends Actor {
type T<: Actor: ClassTag //this doesn't even compile
//...
}
如何使用摘要
type
并摆脱错误?
最佳答案
class M[A <: B: C]
简称
class M[A <: B](implicit c: C[A])
因此,如果您移动
A
对于抽象类型成员,您必须编写类似abstract class M {
type A <: B
implicit protected def c: C[A]
}
并要求任何人实现
M
提供这样的值c
.如果你想要M
非抽象的,您必须需要类型为 C[A]
的构造函数值参数,这又意味着类型 A
必须是构造函数类型参数...编辑 回答评论:符号
A : C
被定义为扩展为 C[A]
类型的隐式值参数.有C
称为上下文绑定(bind),可以理解为求一个类型类C[_]
对于类型 A
.如果您实现 M
您无需重复 implicit
修饰符。为什么会在那里?让我举个例子,使用一个众所周知的类型类 Ordering
: abstract class Foo {
type A
implicit protected def ord: Ordering[A]
protected def seq: Seq[A]
def range: (A, A) = {
val xs = seq
xs.min -> xs.max
}
}
如果您删除了
implicit
,您必须将调用更改为 xs.min
和 xs.max
这需要隐含的 Ordering
.object Bar extends Foo {
type A = Int
val seq = List(8, 34, 5, 21, 3, 13)
val ord = Ordering.Int // don't need to repeat `implicit`
}
Bar.range // (3, 34)
在这里,
Bar
显示您如何提供隐式值参数。这与 ClassTag
相同。 :trait MyClass {
type A
implicit def tag: reflect.ClassTag[A]
}
object StringClass extends MyClass {
type A = String
// type String is statically known, thus compiler gives us this:
val tag = reflect.classTag[String]
}
如果您的子类再次是通用的,您将需要传递提供类标签的责任:
class GenericClass[A1](implicit val tag: reflect.ClassTag[A1]) {
type A = A1
}
关于scala - 抽象类型的 MyClass.this.T 没有可用的 ClassTag,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20580513/