Scala:返回传入类型的实例

时间:2017-05-04 03:08:34

标签: scala reflection types polymorphism

我正在尝试实现一个简单的验证器方法 一个类型作为其第一个参数,一个String作为第二个参数,并始终返回传入类型的实例。没有进一步的麻烦 - 这是方法:

def validateType[T](taip: T, input: String):T = taip match {
    case Boolean => {
      val simplifiedInput = input.replaceAll("[ \\n]", "").toLowerCase()
      if(simplifiedInput.matches("[yn]")){
        simplifiedInput match {
          case "y" => true
          case "n" => false
        }  
      } else{
        validateType(Boolean, StdIn.readLine("$simplifiedInput is not a valid "
      +"answer, please try again"))
      }
    }
  }

但是我收到编译错误(我的IDE中的红色下划线)说: “类型不匹配;找到所需的布尔值(true):T

我意识到T这里是type,但是如何指定我想要返回该类型的实例?我也尝试使用ClassTag,但没有成功。谢谢。

2 个答案:

答案 0 :(得分:3)

您可以使用TypeTag,例如:

  import scala.reflect.runtime.universe._
  def validateType[T](input: String)(implicit typeTag: TypeTag[T]): T = {
    typeTag.tpe match {
      case t if t =:= typeOf[Boolean] => {
        val simplifiedInput = input.replaceAll("[ \\n]", "").toLowerCase()
        if (simplifiedInput.matches("[yn]")) {
          simplifiedInput match {
            case "y" => true.asInstanceOf[T]
            case "n" => false.asInstanceOf[T]
          }
        } else {
          validateType(StdIn.readLine("$simplifiedInput is not a valid "
            + "answer, please try again"))
        }
      }
    }
  }
  validateType[Boolean]("y") //set Boolean type for `T`
  >true

用于测试=:=是否相等的Type。更多比较器见参考。对于返回类型T,您需要asInstanceOf[T] 强制

答案 1 :(得分:3)

由于您需要给定类型的行为,而不是给定的对象或值,因此类型类将是相关的。

trait Validable[T] {
  def validate(input: String): T
}

object Validable {
  implicit val boolean = new Validable[Boolean] {
    def validate(input: String): Boolean = {
      val simplifiedInput = input.replaceAll("[ \\n]", "").toLowerCase()
      if(simplifiedInput.matches("[yn]")){
        simplifiedInput match {
          case "y" => true
          case "n" => false
        }  
      } else {
        validate(StdIn.readLine("$simplifiedInput is not a valid "
        +"answer, please try again"))
    }
  }
  //if you want to write a validator for another type, simply add a new instance.
  implicit val otherTypeValidable = new Validable[OtherType] {
    def validate(input: String): OtherType = ...  
  }
}

def validateType[T](input: String)(implicit validable: Validable[T]): T =
  validable.validate(input)
validateType[Boolean]("y") // returns true

当然,您可以为每个相关类型实现类型类的实例。如果您将其与没有隐式Validable[T]实例的类型一起使用,则会抛出编译错误,因此它比使用反射更安全。