2014-11-07 4 views
1

У меня есть следующие настройки:Scala параметр типа класса стирания

class Test[A](function: A => String) { 
    def process(data: Any) {   //has to be Any since it is user IO 
     if (data of Type A) 
      function(data) 
    } 
} 

Я не могу показаться, чтобы получить typecheck работать. Я попытался добавить неявный TypeTag для проверки [A], но я не смог получить к нему доступ изнутри proccess. Возможно ли совпадение с параметром типа Test в рамках функции процесса?

ответ

2

Используйте ClassTag и match для этой цели:

import scala.reflect.ClassTag 

class Test[A : ClassTag](function: A => String) { 
    def process(data: Any) { //has to be Any since it is user IO 
    data match { 
     case data: A => function(data) 
     case _  => 
    } 
    } 
} 

Благодаря в рамках неявного ClassTag, то match может различать A несмотря на то, что является общим.

+0

очень приятно! Я был очень близок :-), но не совсем – eclipse

+0

На самом деле это не работает. Он компилируется без предупреждения, но во время выполнения данных случая: A соответствует чему-либо – eclipse

0

использованием Shapeless:

class Test[A: Typeable](function: A => String){ 
    import shapeless.syntax.typeable._ 
    def process(data: Any) {   //has to be Any since it is user IO 
     data.cast[A] map { function(_) } 
    } 
    } 

Это один является безопасным, в том, что она возвращает один вариант [A], так что, когда бросок терпит неудачу, Вы можете соответствовать шаблону на None.

+0

благодарит за ваш ответ! Есть ли что-нибудь в стандартной библиотеке, которая может достичь того же? – eclipse

+0

«стандартная библиотека» ('data.isInstanceOf [A]' и 'data.asInstanceOf [A]') работает только частично - до стирания. Таким образом, вы не сможете сопоставить 'List [Int]' vs 'List [String]', это будет просто 'List [_]', что может привести к ложным срабатываниям 'instanceOf' и' ClassCastException', во время выполнения. – ponythewhite

+0

С более новыми версиями scala вы можете использовать TypeTags, которые фиксируют полный тип: http://www.scala-lang.org/files/archive/nightly/docs/library/index.html#scala.reflect.api.TypeTags I просто не может показаться, что он работает. – eclipse

0

Я не уверен, почему data должно быть типа Any (не будет пользовательский ввод быть типа String?), Но если это действительно так, то это, вероятно, отражает ситуацию, когда тип не может ожидаться во время компиляции время. В таком случае, вы, вероятно, хотите способ бросить ошибку времени выполнения при попытке бросить:

class Test[A](function: A => String) { 
    def process(data: Any) = { 
     function(data.asInstanceOf[A]) //might throw an error 
    } 
} 

Или, возможно, использовать Try монады:

class Test[A](function: A => String) { 
    def process(data: Any) = { 
     Try(function(data.asInstanceOf[A])) 
    } 
} 

Конечно, что является наиболее предпочтительным будет чтобы узнать тип data во время компиляции:

class Test[A](function: A => String) { 
    def process(data: A) = { 
     function(data) 
    } 
}