简体   繁体   English

Scala类型边界

[英]Scala type bounds

What is wrong with the code below? 下面的代码有什么问题? I'm getting the following complaint from the compiler on the indicated line: type arguments [Asset] do not conform to trait Worker's type parameter bounds [T <: br.Doable] 我在指定的行上从编译器收到以下抱怨:类型参数[Asset]不符合trait Worker的类型参数bounds [T <:br.Doable]

How is this so? 这是怎么回事? Worker expects a subtype of Doable, and asset extends 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!"
}

When you declare case class Hey[Asset] , you bind a new type variable Asset , you do not refer to case class Asset() extends Doable (you are shadowing the Asset type variable). 当你声明case class Hey[Asset] ,你绑定一个新的类型变量Asset ,你没有引用case class Asset() extends Doable (你正在隐藏Asset类型变量)。 Your code is equivalent to : 您的代码相当于:

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

which obviously won't work. 这显然是行不通的。

The problem is you have confused yourself by using the same value, Asset , to refer to a case class and a type parameter. 问题是你通过使用相同的值Asset来引用案例类和类型参数而使自己感到困惑。

You probably intend to do something like this: 你可能打算做这样的事情:

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

Though it is beside the point, note that I added a parameter to Hey because case classes without parameters have been deprecated. 虽然它不是重点,但请注意我向Hey添加了一个参数,因为不推荐使用不带参数的case类。

This has been asked a lot of times, and I think that the confusion can easily go away if you see the analogy between type parameters and constructor parameters, thinking about them just as different kinds of constructor parameters: type-level and value-level. 这已被问过很多次了,我认为如果你看到类型参数和构造函数参数之间的类比,将它们视为不同类型的构造函数参数:类型级别和值级别,那么混淆很容易消失。

Disclaimer Of course, this is only an analogy and it will break at a lot of different levels and there are a lot of corner cases as with anything Scala; 免责声明当然,这只是一个类比,它会在很多不同的层面上破裂,并且有许多角落案例与Scala一样; but my point here is that it can be useful 但我的观点是它可能有用

At the type level, you can think of <: as a the equivalent of : at the value level: 在类型级别,您可以将<:视为等价于:在值级别:

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)
}  

What I think is the main source of confusion is that at the type level there's no kind distinction between the two sides of <: , and to make things worse you can write T without any (no pun intended) bound, while you cannot do the same at the value level: 我认为混淆的主要原因是,在类型层面上, <:两面之间没有任何区别,并且为了使事情变得更糟,你可以在没有任何(没有双关语意图)约束的情况下编写T ,而你不能这样做价值水平相同:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM