2016-02-12 2 views
2

Я столкнулся с фрагментом кода и не смог понять его. Фрагмент кода:Scala: общий неявный параметр метода

implicit val dummyVisit = Visit("", 1L, 1, 1, 1, 1L) 
    implicit val dummyOrder = Order("", 1L, 1, 1, 1, 1L) 

    def process[T](events : Array[T])(implicit t: T):Unit = { 
    println(t) 
    if(!events.isEmpty) 
     t match { 
     case r: Order => processOrder(events.asInstanceOf[Array[Order]]) 
     case r: Visit => processVisit(events.asInstanceOf[Array[Visit]]); 
     } 
    } 

    def processOrder(arr: Array[Order]): Unit = { println(arr.size) } 
    def processVisit(arr: Array[Visit]): Unit = { println(arr.size) } 

implicit переменная t, требует dummyVisit & dummyOrder существовать.

Вопрос:

  1. Является ли это правильный способ использования implicit parameter?

  2. Есть ли лучший способ получить класс-тип T без использования неявного параметра?

+1

Implicits ищется с использованием правил неявных разрешений http://stackoverflow.com/questions/5598085/where-does-scala-look-for-implicits I не понимаете свой вопрос? вы можете вызвать процесс (xs) в массиве либо посещений, либо ордеров. Если соответствующий имплицит не находится в области видимости, процесс (xs) не будет компилировать –

+1

Похож на плохой способ использования полиморфизма или его отсутствия –

ответ

2

Захват типа аргумента является одним из предполагаемых видов использования неявных аргументов.

Хотя я бы написать что-то вроде этого немного по-разному:

import scala.reflect.ClassTag 

// `sealed` ensures that no extra evidences can be defined elsewhere 
sealed abstract class Evidence[T](implicit val tag: ClassTag[T]) 
object Evidence { 
    implicit object visitEvidence extends Evidence[Visit] 
    implicit object orderEvidence extends Evidence[Order] 
} 

def process[T](events: Array[T])(implicit ev: Evidence[T]) = { 
    import ev.tag // import ClassTag[T] to allow matching on array element types 
    events match { 
    case Array() => // don't process empty arrays 
    case arr: Array[Order] => processOrder(arr) 
    case arr: Array[Visit] => processVisit(arr) 
    } 
} 

Этот код позволяет избежать создания бессмысленные экземпляров фиктивных и типажей с asInstanceOf.

Следующим шагом будет захват самой операции обработки в неявном аргументе и полностью исключение явного match для каждого случая. Это также известно как класса типов шаблона:

sealed trait ProcessArray[T] { 
    def apply(arr: Array[T]): Unit 
} 
object ProcessArray { 
    implicit object processVisitArray extends ProcessArray[Visit] { 
    def apply(arr: Array[Visit]) = { println(arr.size) } 
    } 
    implicit object processOrderArray extends ProcessArray[Order] { 
    def apply(arr: Array[Order]) = { println(arr.size) } 
    } 
} 
def process[T](array: Array[T])(implicit proc: ProcessArray[T]) = { 
    if (array.nonEmpty) proc(array) 
} 
Смежные вопросы