generics with implicit class conversion scala

I have two case class Customer and CustomerResponse and implicit function for conversion from customer to response

case class Customer(name:String)
case class CustomerResponse(customerName:String)

object CustomerImplicits {
  implicit def customer2CustomerResponse(value : Customer) =
                                   new CustomerResponse(value.name)
} 

Im trying to create a generic function where I can pass lot of classes and perform operation

def getEntityArray[T,U](idArray:Array[String]):Array[U] = {
    val records:Array[T] = getRecords[T](idArray)
    if(!records.isEmpty) {
      val ret = records.map( aRec => aRec:U)
      return ret
    }
    else 
      return Array.empty[U]
  }
arr = getEntityArray[Address,AddressResponse](array)

I'm getting an error T does not conform to expected type U. Is there any way to pass the implicit conversion CustomerImplicits to the getEntityArray function

Upvotes: 0

Views: 104

Answers (3)

Mario Galic
Mario Galic

Reputation: 48400

Consider changing from Array to List and pass implicit conversion implicit ev: T => U argument like so

def getEntityList[T, U](ts: List[T])(implicit ev: T => U): List[U]

For example,

def getEntityList[T, U](ts: List[T])(implicit ev: T => U): List[U] = {
  ts.map(ev)
}

import CustomerImplicits._
getEntityList[Customer, CustomerResponse](List(Customer("Picard"), Customer("Worf")))

outputs

res0: List[CustomerResponse] = List(CustomerResponse(Picard), CustomerResponse(Worf))

Upvotes: 3

Feyyaz
Feyyaz

Reputation: 3206

I think you're trying to achieve this:

import scala.reflect._
def getEntityArray[T, U: ClassTag](idArray: Array[String])(implicit t2u: T => U): Array[U] = {
  val records: Array[T] = getRecords[T](idArray)
  if(!records.isEmpty)
    records.map( r => r: U)
  else 
    Array.empty
}
import CustomerImplicits._
getEntityArray[Customer, CustomerResponse](Array.empty)

However, it doesn't seem to be a good approach for several reasons:

  1. Generic types have no relation with the parameters, that's why you can't make use of type inference.
  2. You are using Array, which is basically a Java type, that's why you need to pass the ClassTag context bound to U for it to work. You can try List instead.
  3. Using implicit conversions this way makes the code less readable. Maybe you can just call it explicitly records.map(t2u), and even make t2u a normal parameter.

Upvotes: 1

Raman Mishra
Raman Mishra

Reputation: 2686

Try this:

    implicit class Convert[T](req: List[T]) {

    import CustomerImplicits._

    def gerResp: List[CustomerResponse] = {
      req.flatMap {
        case customer: Customer => customer :: Nil
        case _ => List.empty[CustomerResponse]
      }
    }
  }

  val customer = List(Customer("A"), Customer("B"), Customer("C"))

  println(customer.gerResp)

in place of asInstanceOf you can do any operation you want which is converting T => U

I think this is what you are looking for.

Upvotes: 0

Related Questions