I have these two traits:
sealed trait DbValue {
type R
type T <: DbValue
def content(): R
def copy(newContent: R = content): Option[T]
def toString(): String
}
sealed trait DbValueOps {
type R
type T <: DbValue
def apply(newContent: R): Option[T]
def fromString(newContent: String): Option[T]
def isValidContent(newContent: R): Boolean
}
and want to make a method/class that takes objects that implement both traits, however, the DbValue is implemented by the class, and the DbValueOps is implemented by the companion object.
Example:
case class Column[T <: DbValue with DbValueOps] (val name: String, val cells: Vector[Option[T]] = Vector(), val blank_allowed: Boolean = true) {}
I now want to make a column that is generic over a type that is implemented like this:
case class DbString private (val content: String) extends DbValue {
type R = String
type T = DbString
def copy(newContent: String = content): Option[DbString] = DbString(newContent)
override def toString(): String = content
}
object DbString extends DbValueOps {
type R = String
type T = DbString
def apply(newContent: String): Option[DbString] =
isValidContent(newContent) match {
case true => Some(new DbString(newContent))
case false => None
}
def fromString(newContent: String): Option[DbString] = DbString(newContent)
def isValidContent(newContent: String): Boolean = !newContent.isEmpty
}
However, when I try to make such a Column, with: Column[DbString]("name")
I get the error: type arguments [database.DbString] do not conform to method apply's type parameter bounds [T <: database.DbValue with database.DbValueOps]
Is there a good way to do this? Or how should I change my design?