Для меня одним из наиболее запутанных аспектов системы типов Scala является понимание ковариантности, контравариантности, границ типов и т. д.
Я пытаюсь создать общий признак Repository
, который может быть расширен объектами-компаньонами объектов классов, которые расширяют признак Page
. Идея состоит в том, что объект-компаньон будет отвечать за создание новых экземпляров и т. д. Эти экземпляры страниц необходимо будет очистить, если к ним не обращались в течение некоторого периода времени. Таким образом, базовый трейт Repository
зарегистрирует их в списке репозиториев, которые можно проверить в потоке фонового актора.
Ниже приведена урезанная версия кода. Я получаю сообщение об ошибке type mismatch
при вызове register(pages)
. Компилятор нашел HashMap[String, T]
, но ожидает HashMap[String, Page]
. Я не могу понять, что сделать, чтобы компилятор был доволен. Я могу определить метод регистрации как def register[T <: Page](repo: HashMap[String, T) ...
, но это просто откладывает проблему до ссылки на var repos
, которую я не могу квалифицировать в общем. Я был бы признателен, если бы кто-нибудь мог продемонстрировать правильный способ указания типов.
EDIT Я могу заставить его работать, если объявлю хэш-карту как HashMap[String, Page]
, а затем приведу значение page
, полученное из хэш-карты, с помощью page.asInstanceOf[String, T]
. Есть ли способ избежать броска?
trait Page {
val id = Random.hex(8)
private var lastAccessed = new Date
...
}
object Page {
import scala.collection.mutable.HashMap
trait Repository[T <: Page] {
private val pages = new HashMap[String, T]
register(pages)
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 = now
page
case None =>
this()
}
}
...
}
private var repos: List[HashMap[String, Page]] = Nil
private def register(repo: HashMap[String, Page]) {
repos = repo :: repos
}
...
}
class CoolPage extends Page
object CoolPage extends Page.Repository[CoolPage] {
def newPage = new CoolPage
}
val p = CoolPage()