2015-04-03 52 views
1

我正在使用「案例類而不是枚舉」模式,並且想要列出每個「枚舉」的所有值以及一些方法。所以我決定不僅僅從一個密封的抽象類派生我的案例類,而是從一個叫做Lookup的超類派生所有密封的抽象類,並定義一個從中派生抽象類的伴隨對象的LookupTrait。如何製作一個可以實例化類的參數化特徵?

abstract class Lookup { 
    val name: String 
    override def toString = name 
} 

trait LookupTrait[T<:Lookup] { 
    val all: Map[String, T] 
    val default: T 
    def withName(name: String): T = 
    if(all.contains(name)) all(name) 
    else default 
} 

和示例查詢看起來是這樣的:

sealed case class StudyGoal(override val name: String) extends Lookup 

object StudyGoal extends LookupTrait[StudyGoal] { 

    override val all = Map(
     "present new evaluation method" -> StudyGoal("present new evaluation method"), 
     "evaluate existing product" -> StudyGoal("evaluate existing product"), 
     "develop new theoretical model" -> StudyGoal("develop new theoretical model"), 
     "unknown" -> StudyGoal("unknown") 
    ) 
    override val default = StudyGoal("unknown") 
} 

我寧願只是在每個查詢的同伴對象定義字符串列表,並有特質實例的情況下類。但是,當我在Scala中發現三種不同的反射方式時 - 使用Manifest,TypeTag,並按照in the documentation所述獲得類的構造函數,它們都似乎需要有一個類的實例存在,讓他們在參數化的LookupTrait特徵中工作。

我想有這樣的:

abstract class Lookup { 
    val name: String 
    override def toString = name 
} 

trait LookupTrait[T<:Lookup] { 
    val allNames: List[String] 

    val default: T = //Instantiate a T using the string "unknown". 
    //It is OK that this string will be the same for all Lookups. 

    val all: Map[String, T] = allNames.map(
    n => n -> //instantiate a T here, using n as the parameter 
) += default 

    def withName(name: String): T = 
    if(all.contains(name)) all(name) 
    else default 
} 

sealed case class StudyGoal(override val name: String) extends Lookup 

object StudyGoal extends LookupTrait[StudyGoal] { 

    override val allNames = List(
     "present new evaluation method"), 
     "evaluate existing product", 
     "develop new theoretical model" 
    ) 
} 

回答

0
從您的意見

所以,你的「我想有什麼」一節,它看起來像你想的「實例T」進一步參數。你可以添加一個抽象方法到LookupTrait,子類將需要實現;它可能有這樣的簽名:

def instantiateElement(name: String): T 

雖然我對你想要做什麼感到困惑。 Scala枚舉意味着像Java枚舉一樣使用 - 用於處理一組固定的,有限的選擇。您通常將每個元素綁定到一個PascalCase名稱,以便您以後可以對這組名稱匹配未知值。你的情況看起來不像固定的有限集合,更像是一個動態的開放集合。也許你根本不需要這些;也許一個普通的Set[String]就足夠了。

1

我有一個lib,做一些接近,只是你需要定義的情況下對象,而不是僅僅使用字符串:https://github.com/lloydmeta/enumeratum

它由是,隨着一點點的工作/修改,可能可能導致宏動力正是你想要的(在編譯時,基於字符串定義實例)