Search code examples
genericsscalabounds

Scala Upper Bounds : value is not a member of type parameter


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.


Solution

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