Scala 没有可用于MyClass的类标记。此.T用于抽象类型

Scala 没有可用于MyClass的类标记。此.T用于抽象类型,scala,type-erasure,type-parameter,type-members,Scala,Type Erasure,Type Parameter,Type Members,这很有效 class MyClass[T<: Actor: ClassTag] extends Actor { //.... } 即使在以下情况下: class MyClass extends Actor { type T<: Actor: ClassTag //this doesn't even compile //... } 类MyClass扩展了Actor{ T型 并要求实现M的任何人提供这样一个值c。如果希望M非抽象,则必须要求类型为c[a]的构造函数值参数,

这很有效

class MyClass[T<: Actor: ClassTag] extends Actor {
  //....
}
即使在以下情况下:

class MyClass extends Actor {
  type T<: Actor: ClassTag //this doesn't even compile
  //...
}
类MyClass扩展了Actor{
T型
并要求实现
M
的任何人提供这样一个值
c
。如果希望
M
非抽象,则必须要求类型为
c[a]
的构造函数值参数,这反过来意味着类型
a
必须是构造函数类型参数


Edit回答注释:符号
A:C
被定义为扩展为
C[A]
类型的隐式值参数。其中
C
被称为上下文绑定,可以理解为请求类型类
C[\ux]
用于类型
A
。如果实现
M
,则无需重复
隐式
修饰符。为什么会出现此修饰符?让我给您一个使用著名类型类
排序
的示例:

 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

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
}

有趣的是,我对它进行了一些研究,产生了两个问题:1)为什么方法
c
M
中是隐式的:?非隐式的方法不是等同于使用参数化类型的前两个版本吗?2)在
ClassTag
的特殊情况下,不需要构造函数值(我将其替换为类中的
override val c=classTag[…]
)。这通常不可能吗?我如何在子类中提供
c:ClassTag
的实现?它应该是什么样子?似乎在
object StringClass extensed MyClass
-type A=
String
和val tag=reflect.ClassTag[
String
]中存在冗余重复?我可以避免这种情况吗?你能给我举个例子吗?如果你想要M非抽象的,你必须需要一个C[a]类型的构造函数值参数,这反过来意味着a类型必须是构造函数类型参数吗?@Alex你或者静态地知道类型
a
(示例
StringClass
),否则它将保持泛型。然后,任何具体类都需要通过构造函数获取class标记(例如
GenericClass
),因此,您或多或少会在离开的地方结束。关于您的第一条注释:类型参数在运行时被删除,这就是为什么您首先有标记,所以它们不是多余的。但是,如果您不使用数组,您将非常少需要它们。
 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
   }
 }
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)
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
}