First of all, it should be noted that mutable HashMap is invariant: class HashMap [A, B] . Although the immutable version is covariant in value: class HashMap [A, +B] .
Secondly, your repos variable must be a polymorphic collection, which means that some information like compile time is lost when you put things in there.
But since you are using mutable HashMap , repos cannot actually be a valid polymorphic collection due to the invariance of HashMap . To illustrate why, let's assume that the page is a class (so we can create one), and we put the HashMap [String, CoolPage] in the repos list. Then we could do this:
val m = repos.head
So, the compiler gives you an error to protect you from this.
I think you can fix your code by making the repository covariant:
trait Repository[+T <: Page] { private[this] val pages = new HashMap[String, T] register(this) def newPage: T def apply(): T = { val page = newPage pages(page.id) = page page } def apply(id: String): T = { pages.get(id) match { case Some(page) => page.lastAccessed = new Date page case None => this() } } }
And changing repos to Repository[Page] list:
private var repos: List[Repository[Page]] = Nil private def register(repo: Repository[Page]) { repos = repo :: repos }
And remember that polymorphic collections (such as repos ) cause you to lose information about the types of compilation times of elements: if you put Repository[CoolPage] , you will only get Repository[Page] back and have to deal with it.
update : removed .asInstance[T] from the Repository code by making pages private[this] .
source share