Вопрос

Now I'm not pretending that this code is good programming practice, but I don't understand why it won't compile. What's going on here?

object CustomTo extends App {
  val thing:Something = new Something
  val str:String = thing.to[String]
  println(str)
}

class Something {
  def to[String]:String = {
    "hello"
  }
}

Compiler output:

CustomTo.scala:9: error: type mismatch;
 found   : java.lang.String("hello")
 required: String
    "hello"
    ^
one error found
Это было полезно?

Решение

You named your type parameter String instead of T, but that doesn't make it less abstract, it can still be anything.

def to[String]:String 
// is the same as
def to[T]:T

If you want to create a generic .to[T] function that returns hello when called with String, i.e. you want to pattern match on a type, you can use a TypeTag:

Edit: I just overlooked that the return type needs to be T, which means a useless cast has to be there, see below.

import reflect.runtime.universe._

def to[T : TypeTag] = (typeOf[T] match {
  case t if t =:= typeOf[String] => "hello"
  case t if t =:= typeOf[Int] => 1
  case _ => ???
}).asInstanceOf[T]

and:

scala> to[String]
res13: String = hello

scala> to[Int]
res14: Int = 1

scala> to[Double]
scala.NotImplementedError: an implementation is missing
...

I am not sure there is a way to have the compiler infer on its own that things inside the pattern match have the correct types. It may be possible with ClassTag, but you would lose type safety with .to[List[Int]] and similar...

Другие советы

The compiler expects "String", if you would have put

class Something {
  def to[T]:T = {
    "hello"
  }
}

You would get something like "required: T". In other words, you bind "String" to some type. There is not a lot of sense making in your example right now. What are you trying to accomplish?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top