Почему метод Scala PartialFunction isDefinedAt всегда возвращает true? - PullRequest
0 голосов
/ 01 апреля 2020

мой код, как показано ниже.

    case class C[T]() {
      val pf:PartialFunction[Any,Any] = {
        case i:T => i
      }
    }

    println(C[Int]().pf.isDefinedAt(-1.0))

это печатает true. Почему это происходит?

1 Ответ

3 голосов
/ 01 апреля 2020

Из-за типа стирания ваш код в основном равен:

case class C[T]() {
  val pf:PartialFunction[Any,Any] = {
    case i:Any => i // this matches everything
  }
}

, вы можете использовать TypeTag s, чтобы исправить это:

import scala.reflect.runtime.universe._
case class C[T: TypeTag]() {
  def pf[U: TypeTag]: PartialFunction[U, Any] = {
    case i if typeOf[U] <:< typeOf[T] => i
  }
}

используется:

@ C[Int]().pf.isDefinedAt("")
res41: Boolean = false

@ C[Int]().pf.isDefinedAt(34)
res42: Boolean = true

они практически равны

@ C[Int]().pf[String].isDefinedAt("")
res41: Boolean = false

@ C[Int]().pf[Int].isDefinedAt(34)
res42: Boolean = true

, где выводится тип U - у него есть ограничение, что он может быть настолько точным, как знание компилятора о типе, когда TypeTag требуется.

Вы также можете попытаться использовать ClassTag[T] для использования отражения во время выполнения ... но для примитивов это не получится

case class C[T]()(implicit classTag: scala.reflect.ClassTag[T]) {
  def pf[U: TypeTag]: PartialFunction[U, Any] = {
    case i if classTag.runtimeClass.isInstance(i) => i
  }
}

, что приведет к

@ C[Int]().pf.isDefinedAt(34)
res2: Boolean = false

@ C[Int]().pf.isDefinedAt("")
res3: Boolean = false

Дело в том, что classTag разрешит Scala int, в то время как время выполнения покажет java.lang.Int:

@ case class C[T]()(implicit classTag: scala.reflect.ClassTag[T]) {
    def pf: PartialFunction[Any, Any] = {
      case i => println(s"T = ${classTag.runtimeClass.getName}, here: ${i.getClass.getName}")
    }
  }
defined class C

@ C[Int]().pf.isDefinedAt(34)
res7: Boolean = true

@ C[Int]().pf(34)
T = int, here: java.lang.Integer
res8: Any = ()

В общем, здесь нет идеального решения, вы можете прочитать больше о похожих вопросах здесь и здесь .

...