特征中的Scala泛型类型

时间:2014-03-17 16:46:09

标签: scala generics

我想做什么:

trait BasicModel {
  type U <: BasicModel

  def -(that: U): BasicModel
  ...
}

class MatrixFactorizationModel(val W: DenseMatrix[Double], val b: Double) extends  BasicModel {
  type U = MatrixFactorizationModel

  def -(that: MatrixFactorizationModel): MatrixFactorizationModel =  new MatrixFactorizationModel(W + that.W, b - that.b)
  ...
}

abstract class SAG [T <: BasicModel#U : ClassTag] {
  //type T <: BasicModel#U    I also tried like that

  def modelDerivative(idx: Index, cstDerivative: Double): T

  def compute(): T = {
    SumDerivative = SumDerivative - modelDerivative(idx, Hist(idx))
  }
}

当调用compute时,我收到了这个错误:

type mismatch;
found   : T
required: _129.U where val _129: T
    SumDerivative = SumDerivative - modelDerivative(idx, Hist(idx))

我不明白为什么这不起作用,因为T是BasicModel #U。有人可以解释我,给我一个替代方案吗?


编辑:

我在T&lt;:BasicModel中更改了SAG T&lt;:BasicModel #u,当我使用T在T#U中更改它时:

abstract class SAG [T <: BasicModel : ClassTag] extends Optimizer {

  def modelDerivative(idx: Index, cstDerivative: Double): T#U

   ...
}

但是:

type mismatch;
found   : T#U
required: _128.U where val _128: T#U
    SumDerivative = SumDerivative - modelDerivative(idx, Hist(idx))

1 个答案:

答案 0 :(得分:1)

它类似于BasicModel中定义的类型,U是BasicModel实例的成员。它类似于Java中静态/实例变量之间的区别。要匹配类型定义,您需要完全相同的类型。如果它是静态的,你就无法在子类MatrixFactorizationModel中覆盖它。

SAG中的

T <: BasicModel表示任何 T&lt;:BasicModel#U(父#U),其中#U可以是BasicModel的任何子类型。即使您在实例化SAG实例的任何地方都可能碰巧指定了MatrixFactorizationModel,但编译器并不知道您在此上下文中具有哪些特定T,或者它是同一U的子类型。

你可能会有更好的运气trait BasicModel { def [T<:BasicModel]-(that:T):T }。它有点冗长,如果您有很多方法签名要输入,可能会非常痛苦,但有时这样的签名效果更好。