scala - yet another type mismatch

2019-08-13 11:17发布

问题:

type mismatch; found : IDataContext[_$1] where type _$1 <: DBObject required: IDataContext[DBObject] Note: _$1 <: DBObject, but class IDataContext is invariant in type A. You may wish to define A as +A instead. (SLS 4.5)

This problematic part "required: IDataContext[DBObject]" is actually defined like this.

abstract class IDataContextBuilder[+A <: DBObject] {

  def initXDataPoints(dataContext: IDataContext[A]): Unit
}

I changed it to following and it works but it looks quite redundant

abstract class IDataContextBuilder[+A <: DBObject] {

  def initXDataPoints[A <: DBObject](dataContext: IDataContext[A]): Unit
}

Now issue is in implementation of above method:

override def initXDataPoints[Dim1Agg](dataContext: IDataContext[Dim1Agg]): Unit = { ...}

method initXDataPoints overrides nothing. Note: the super classes of class Dim1DataContextBuilder contain the following, non final members named initXDataPoints: def initXDataPoints[A <: DBObject](dataContext: IDataContext[A]): Unit

Dim1Agg is subtype of DBObject

回答1:

Looking at the first code snippet I think you have a variance problem: Type parameter A is covariant (defined with a +) however it appears in a contra-variant position - the argument dataContext to the method initXDataPoints. What you can do is parameterize initXDataPoints with an lower bound like that:

def initXDataPoints[B >: A](dataContext: IDataContext[B]): Unit

Edit:

trait DBObject
trait Dim1Agg extends DBObject
trait IDataContext[A]

abstract class IDataContextBuilder[+A <: DBObject] {
  def initXDataPoints[B>:A](dataContext: IDataContext[B]): Unit
}

class Dim1DataContextBuilder extends IDataContextBuilder[Dim1Agg] {
  override def initXDataPoints[B >: Dim1Agg](dataContext: IDataContext[B]): Unit = ???
}

The rationale behind adding the lower bound type parameter B is that the implementation will not be able to use any specific properties of the type A. Using specific properties of A may break under inheritance and therefore are disallowed by the scala compiler. This is explained very well in the book Programming in Scala 2nd edition chapter 19 (Type parameterization). I suggest to read the whole chapter, and look for specific example that explains this in section 19.4.



标签: scala