2015-05-01 3 views
0

У меня есть функция форматирования строк fmt(v:Any): String, которая должна выполнять разные вещи в зависимости от типа времени выполнения v. Так что это выглядит примерно так:Определить, что Any на самом деле является значением scala перечисления

def fmt(v:Any): String = { 
    v match { 
    case a: Int => "Int: " + a 
    case a: String => "\"" + a + "\"" 
    case a => throw new IllegalArgumentException(s"??? '$a', ${a.getClass.getCanonicalName}?!") 
    } 
} 

Это бросает IllegalArgumentException("??? 'myVal', scala.Enumeration.Val?!"), когда я прохожу в значение перечисления Scala. Однако добавление

case a: scala.Enumeration.Val => "Hello enum" 

не компилируется: объект Перечень не является членом пакета Скале Примечание: класс Перечень существует, но это не имеет никакого объекта компаньона.

Как я могу обнаружить, что экземпляр, переданный в, является значением перечисления scala?

if (a.getClass.getCanonicalName == "scala.Enumeration.Val") должен работать, но чувствует себя довольно взломанным - есть ли фактически типизированные шаблоны, которые я могу сделать вместо этого?

ответ

5

Вы совершили две ошибки. Во-первых, имя класса для публичного API перечисления - Value не Val. Во-вторых, если обратиться к внутренним классам, вы используете #, а не .. Последний обозначает внутренний класс конкретного экземпляра; первое означает «для некоторого Enumeration, мне все равно, это экземпляр его внутреннего значения класса»).

Так, написать это:

case a: scala.Enumeration#Value => "Hello, enum!" 

Если вы на самом деле означает, что вы должны знать, когда это защищенный класс реализации Val вместо общественного облицовочный Value, вы не можете легко, потому что, ну, он защищен. Предполагается, что это деталь реализации. Но вы можете поместить свой матч внутри того, что расширяет Enumeration, а затем вы можете получить Val. (С использованием # обозначение.)

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