Метод с параметром типа не компилируется

Я не претендую на то, что этот код является хорошей практикой программирования, но я не понимаю, почему он не компилируется. Что тут происходит?

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

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

Вывод компилятора:

CustomTo.scala:9: error: type mismatch;
 found   : java.lang.String("hello")
 required: String
    "hello"
    ^
one error found

person tsjnsn    schedule 20.06.2013    source источник
comment
то, что вы здесь делаете, на самом деле очень плохая практика... Вы назвали свой параметр типа String. просто замените его чем-то вроде T и вы поймете, почему он не компилируется.   -  person tenshi    schedule 20.06.2013
comment
возможный дубликат ошибки параметра типа Scala, не являющейся членом тип параметра   -  person senia    schedule 20.06.2013


Ответы (2)


Вы назвали свой параметр типа String вместо T, но это не делает его менее абстрактным, он может быть чем угодно.

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

Если вы хотите создать общую функцию .to[T], которая возвращает приветствие при вызове с String, т. е. вы хотите, чтобы тип соответствовал шаблону, вы можете использовать TypeTag:

Правка: я просто упустил из виду, что тип возвращаемого значения должен быть T, а это означает, что должно быть бесполезное приведение, см. ниже.

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]

а также:

scala> to[String]
res13: String = hello

scala> to[Int]
res14: Int = 1

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

Я не уверен, что есть способ заставить компилятор самостоятельно сделать вывод о том, что вещи внутри совпадения с шаблоном имеют правильные типы. Это может быть возможно с ClassTag, но вы потеряете безопасность типов с .to[List[Int]] и подобным...

person gourlaysama    schedule 20.06.2013
comment
Принято за чтение моих мыслей. Есть ли способ сузить тип возвращаемого значения? val str:String = thing.to[String].asInstanceOf[String] Можно ли вернуть запрошенный тип по умолчанию? - person tsjnsn; 20.06.2013
comment
@tsjnsn хорошая мысль, тип возвращаемого значения не очень приятный. Смотрите мою правку. - person gourlaysama; 20.06.2013

Компилятор ожидает "String", если бы вы поставили

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

Вы получите что-то вроде "required: T". Другими словами, вы привязываете «String» к некоторому типу. В вашем примере сейчас не так много смысла. Что вы пытаетесь достичь?

person Felix    schedule 20.06.2013
comment
Я хотел иметь возможность сказать что-то вроде thing.to[String] или thing.to[Int] , поэтому такое определение: (хотя типы нельзя сравнивать, как я показываю) def to[A]:A = { if (A == String) => "hello"; if (A == Int) => 0; } - person tsjnsn; 20.06.2013