Reputation: 777
I tried to write some function which does different things according to the input type. For example, I do this:
def Foo[T](inList: List[String]): ArrayBuffer[T] = {
val out: ArrayBuffer[T] = new ArrayBuffer[T]()
inList.map ( x => {
val str = x.substring(1)
out += str.asInstanceOf[T]
})
out
}
but if I call this function with Foo[Long](new List("123","2342"))
, I get an ArrayBuffer
with String
s, not Long
s. Sorry for my noob question, i want understand scala and generics.
Upvotes: 2
Views: 324
Reputation: 815
So that, runtime equivalent of your code will look like
def Foo(inList: List[String]): (ArrayBuffer[Object]) = {
val out: ArrayBuffer[Object] = new ArrayBuffer[Object]()
inList.map ( x => {
val str=x.substring(1)
out += str.asInstanceOf[Object]
})
(out)
}
Summing up, your code should look like this:
import scala.collection.mutable.ArrayBuffer
// here we define how convert string to longs
implicit def stringToLong(s: String) = s.toLong
// now this function requires to have converter from string to T in context
def Foo[T](inList: List[String])(implicit f: (String) => T): (ArrayBuffer[T]) = {
val out: ArrayBuffer[T] = new ArrayBuffer[T]()
inList.map { x =>
val str = x.substring(1)
out += f(str) // here we apply converter
}
out
}
// when function is called, appropriate implicit converter from context will be used
Foo[Long](List("51", "42"))
Upvotes: 4
Reputation: 11479
Casting a String
to a Long
does not make it a Long, it is an error, so you should get a runtime error saying that you cannot cast String to Long. Since T does not place any restrictions on what it can be, you cannot expect to call any method that isn't on all objects (toString
is for example). You could provide that function yourself (which is almost the exact signature of map, so you could just use that):
def convert[T](in: List[String])(convert: String => T): List[T] =
in.map(convert)
Or make sure the objects are of a type that you know of the methods on (using a type bound):
trait CanConvertTo[T] {
def convert: T
}
case class Example(value: String) extends CanConvertTo[Long] {
def convert = value.toLong
}
def convert[T](in: List[CanConvertTo[T]]): List[T] = in.map(_.convert)
Upvotes: 1