Scala Upper Bounds : value is not a member of type

2019-09-01 18:50发布

问题:

Why can the Price not find the attribute value on the SeqValue? It seems so simple that is should work.

Im getting the error

[error]   .... value value is not a member of type parameter SeqValue
[error]   def recalc[SeqValue](input:SeqValue) = Price(1 + seq, input.value)    

for the following code

sealed trait SeqValue {
  def seq:Int
  def value:Float
  override def toString = ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE)
}

sealed trait Calc {
  type S <: SeqValue
  def recalc[S](input:S):SeqValue
}

case class Price(seq:Int=0, value:Float=.0f) extends SeqValue with Calc {
  def recalc[SeqValue](input:SeqValue) = Price(1 + seq, input.value)
}

The idea is that you can recalc on the price object, and pass in any type of object that implements SeqValue, because SeqValue has a value.

回答1:

The type member S in Calc is getting shadowed by type parameter S of recalc method.

Second mistake: The abstract type S will have to be defined in class Price.

The following should work:

sealed trait SeqValue {
  def seq:Int
  def value:Float
  override def toString = ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE)
}

sealed trait Calc {
  type S <: SeqValue
  def recalc(input:S):SeqValue
}

case class Price(seq:Int=0, value:Float=.0f) extends SeqValue with Calc {
  type S = SeqValue
  def recalc(input:SeqValue) = Price(1 + seq, input.value)
}

Edit: (in response to the comment)

I don't understand what you're exactly trying to do, but you could separate out the type definition in a separate mixin trait.

trait SAsSeqValue {
  type S = SeqValue
}

case class Price(seq:Int=0, value:Float=.0f) extends SeqValue with Calc with SAsSeqValue {      
  def recalc(input:SeqValue) = Price(1 + seq, input.value)
}