Scala类型边界

时间:2013-12-30 15:39:03

标签: scala

以下代码有什么问题?我在指定的行上从编译器收到以下抱怨:类型参数[Asset]不符合trait Worker的类型参数bounds [T<:  br.Doable]

这是怎么回事? Worker期望子类型为Doable,资产扩展为Doable。

trait Doable

trait Worker[T<:Doable] {
  def hey():String
}

case class Asset() extends Doable

case class Hey[Asset] extends Worker[Asset] { // << error here
  def hey() = "You!"
}

3 个答案:

答案 0 :(得分:6)

当您声明case class Hey[Asset]时,绑定一个新的类型变量Asset,您不会引用case class Asset() extends Doable(您正在隐藏Asset类型变量)。 您的代码相当于:

  case class Hey[A] extends Worker[A] {
    ...
  }

显然无效。

答案 1 :(得分:2)

问题是您使用相同的值Asset来引用案例类和类型参数,从而使您感到困惑。

你可能打算这样做:

case class Hey[T](str: String) extends Worker[Asset] { 
  def hey() = "You!"
}

虽然它不是重点,但请注意我向Hey添加了一个参数,因为不推荐使用没有参数的案例类。

答案 2 :(得分:0)

这已被问过很多次了,我认为如果你看到类型参数和构造函数参数之间的类比,将它们视为不同类型的构造函数参数,那么混淆很容易消失:类型级别和值-水平。

  

免责声明当然,这只是一个类比,它会在很多不同的层面上破解,并且有很多极端情况与Scala一样;但我的观点是它可以有用

在类型级别,您可以将<:视为价值级别的:的等价物:

class TypeParamsVsVals {

  type X
  type X1 <: X

  class Buh[T <: X]
  class Oh[T1 <: X1] extends Buh[T1]
  // wait for Scala 3
  // class Oh[T1 <: X1] extends Buh[T = T1]

  type x
  type x1 <: x

  class buh(val t: x)
  class oh(val t1: x1) extends buh(t = t1)
}  

我认为混淆的主要原因是在类型级别<:的双方之间没有任何区别,为了使事情变得更糟,你可以写T而不用任何({1}}双关语,但你不能在价值水平上做同样的事情:

class NoBounds[T]
// same as 
class AltNoBounds[T <: Any]

// you cannot write
// class noBounds(val t)
class noBounds(val t: Any)