2015-09-21 2 views
1

Я думал, что должно быть возможно написать общую функцию, которая работает для всех значений Enumeration. Я попытался простой парсер первый, но мне не удалось:Scala: общий синтаксический анализатор для значений перечисления

object Weekday extends Enumeration { 
    type Weekday = Value 

    val MONDAY = Value("MONDAY") 
    val OTHER = Value("OTHER") 

    implicit def valueToWeekday(v: Value): Weekday = v.asInstanceOf[Weekday] 
    implicit def stringToWeekday(s: String): Weekday = Weekday.withName(s) 
} 

object Enumerations { 
    import Weekday._ 
    println("Welcome to the Scala worksheet") 

    def parseEnumeration[T <: Enumeration](s: String)(implicit ev: T): T#Value = { 
    ev.withName(s) 
    } 

val test = parseEnumeration[Weekday]("MONDAY") 
} 

Так как я могу написать функцию generict принимая тип перечисления в качестве параметра и возвращает значение этого типа? Я немного смущен здесь с Object и внутренним типом с тем же именем.

+0

Немного связано: https://stackoverflow.com/questions/21511656/declare-generic-method-returning-enumeration & https://stackoverflow.com/questions/14451152/scala-class-that-handles-enumerations- обобщенно – dskrvk

ответ

1

Во-первых, ваш неявный метод valueToWeekday на самом деле ничего не делает, так как Weekday - просто псевдоним для Value в этом контексте.

Во-вторых, ваш неявный метод stringToWeekday является рабочим, хотя и не общим, преобразованием из строки в значение его перечисления.

Однако нетрудно сделать stringToWeekday общий. Вам просто нужно передать перечисление функции, как и в parseEnumeration. Поскольку вы сделали доказательства в parseEnumeration неявными, все, что вам нужно сделать, это указать соответствующее имплицитное значение в контексте. В качестве альтернативы вы можете передать доказательства в явном виде.

Таким образом, вы можете удалить эти неявные преобразования (и псевдоним типа, так как конфликт имен немного вводит в заблуждение).

object Weekday extends Enumeration { 
    val Monday = Value("MONDAY") 
    val Other = Value("OTHER") 
} 
  1. неявный способ:

    def parseEnumeration[T <: Enumeration](s: String)(implicit ev: T): T#Value = ev.withName(s) 
    
    implicit val evidence = Weekday 
    val weekday = parseEnumeration("MONDAY") // results in the value Weekday.Monday 
    
  2. Явный путь:

    def parseEnumeration[T <: Enumeration](s: String, enumeration: T): T#Value = enumeration.withName(s) 
    
    val weekday = stringToEnumerationValue("MONDAY", Weekday) // results in the value Weekday.Monday 
    

Третий вариант будет использовать ClassTag в качестве доказательства, что помещать в контекст компилятором через ген ric параметры. Тем не менее, это требует отражения, чтобы на самом деле вызвать метод withName, и я бы отговаривал идти этим путем.

Смежные вопросы