2015-04-08 2 views
0

У меня есть класс, который имеет некоторые Vals к нему, мне нужна функция, которая возвращает Vals на основе строки, переданной вшаблон соответствует строке в поле

case class AThing(name: String, description: String) 

object AThing { 

    val FIRST_THING = AThing("FIRST_THING", "A first thing desc") 
    val SECOND_THING = AThing("SECOND_THING", "A second thing desc") 
    val THIRD_THING = AThing("THIRD_THING", "A third thing desc") 

} 

Теперь у меня есть следующее решение:

def get(name: String): AThing = { 

    name match { 
    case "FIRST_THING" => FIRST_THING 
    case "SECOND_THING" => SECOND_THING 
    case "THIRD_THING" => THIRD_THING 
    } 

} 

есть ли лучший образец для этого .. Я клянусь, что я помню, что-то вдоль линий этого:

def get(name: String): AThing = { 
    name match { 
    case `name` => AThing.`name` 
    // OR 
    case `name` => AThing.{{name}} 
    } 
} 

Спасибо.

+0

Второй метод здесь не применим. Единственный другой способ, которым я могу думать о том, чтобы найти «AThing» по имени, - это иметь vals в «List» и использовать 'find'. –

ответ

3

Вы можете использовать Java отражение, чтобы получить поле:

def get(name: String): AThing = 
    AThing.getClass.getDeclaredMethod(name).invoke(AThing).asInstanceOf[AThing] 

В качестве метода object AThing вы также можете иметь его в таком виде:

object AThing { 
    val FIRST_THING = ??? 
    // ... other things 

    def get(name: String) = 
    this.getClass.getDeclaredField(name).get(this).asInstanceOf[AThing] 
} 

Или с Scala отражения:

import scala.reflect.runtime.universe._ 
import scala.reflect.runtime.currentMirror 
def get(name: String) = 
    currentMirror.reflect(AThing) 
       .reflectField(typeOf[AThing.type].member(TermName(name)).asTerm) 
       .get.asInstanceOf[AThing] 

Чтобы добавить дополнительную безопасность, вы можете вернуть ее Option:

def getOption(name: String): Option[AThing] = util.Try(get(name)).toOption 

Но также рассмотреть вопрос о моделировании этой концепции с Map:

object AThing { 
    val things: Map[String, AThing] = Seq(
    AThing("FIRST_THING", "A first thing desc"), 
    AThing("SECOND_THING", "A second thing desc"), 
    AThing("THIRD_THING", "A third thing desc") 
).map(thing => thing.name -> thing).toMap 
} 

Затем вы можете использовать AThing.things("FIRST_THING"), чтобы получить вещь по имени, или получить Option: AThing.things.get("FIRST_THING").

+0

Спасибо за предложения, в идеале не хотел бы решения карты, так как будет означать много повторений, когда это довольно простая функция, даст другим возможность – andyroo