以下代码有什么问题?我在指定的行上从编译器收到以下抱怨:类型参数[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!"
}
答案 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)