對我的Scala的類型系統的更混亂的一個方面是理解協方差,逆變,類型限制等什麼是指定型方差的陪伴方法的正確方式對象
我想創建一個通用的Repository
特徵,可以通過擴展Page
特徵的類的伴隨對象對象進行擴展。這個想法是,伴侶對象將負責創建新的實例等。如果這些頁面實例在一段時間內未被訪問,則需要對其進行清理。因此,基礎Repository
特徵將把它們註冊到可以在後臺主角色線程中檢查的存儲庫列表中。
下面是代碼的簡化版本。在致電register(pages)
時,我收到type mismatch
錯誤。編譯器發現HashMap[String, T]
但期待HashMap[String, Page]
。我無法弄清楚如何讓編譯器感到滿意。我可以將註冊方法定義爲def register[T <: Page](repo: HashMap[String, T) ...
,但這只是將問題推遲到我無法一般限定的var repos
的引用。如果有人能夠證明指定類型的正確方法,我將不勝感激。
編輯我可以得到它,如果我宣佈HashMap中的HashMap[String, Page]
再投從HashMap中提取出來的page.asInstanceOf[String, T]
的page
值工作。有沒有辦法避免演員陣容?
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()
很好的答案。我錯過了關於可變HashMap的不變性。衛生署!您的描述是現貨。我還喜歡'private [this]'的技巧,讓編譯器知道'pages'不會在任何可能導致差異問題的地方使用。感謝您的幫助。 – sellmerfud 2011-03-11 04:22:07