Scala:返回传入类型的实例

Scala:返回传入类型的实例,scala,reflection,types,polymorphism,Scala,Reflection,Types,Polymorphism,我正在尝试实现一个简单的验证器方法,它需要 一个类型作为第一个参数,一个字符串作为第二个参数,并且总是返回传入类型的实例。无需进一步ado-这是一种方法: def validateType[T](taip: T, input: String):T = taip match { case Boolean => { val simplifiedInput = input.replaceAll("[ \\n]", "").toLowerCase() if(simp

我正在尝试实现一个简单的验证器方法,它需要 一个类型作为第一个参数,一个字符串作为第二个参数,并且总是返回传入类型的实例。无需进一步ado-这是一种方法:

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
这里有一个
类型,但如何指定我要返回该类型的实例?我也尝试过使用ClassTag,但没有成功。谢谢。

您可以使用它,如:

  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
在那里,
=:=
用于测试
类型
是否相等。更多比较器参见参考。对于返回类型
T
,您需要通过
将其转换为[T]
,您可以使用它,如:

  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

在那里,
=:=
用于测试
类型
是否相等。更多比较器请参见参考。对于返回类型
T
,您需要通过
将其转换为[T]

因为您想要的是给定类型的行为,而不是给定的对象或值,所以typeclass是相关的

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

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

因为您想要的是给定类型的行为,而不是给定的对象或值,所以typeclass是相关的

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

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

谢谢chengpohi!typeTag是隐式的,也是第一个参数(客户端指定的类型)消失了,那么这一行
t=:=typeOf[Boolean]
如何确定“[yn]”属于Boolean类型呢?@vasigorc,您可以将其用作
validateType[Boolean](“y”)
,在那里,为
T
设置泛型类型
Boolean
ClassTag
未弃用,您将其与
Manifest
@AlexeyRomanov混淆,谢谢澄清。
/@弃用(“使用scala.reflect.ClassTag(捕获擦除)或scala.reflect.runtime.universe.TypeTag(捕获类型)或两者兼而有之“,“2.10.0”)特征清单[T]扩展了类清单[T]
Hello@chengpohi,我给Cyrille的答案是正确的。您的方法确实消除了编译错误,但如果输入正确([YyNn]),程序会意外终止。谢谢chengpohi!typeTag是隐式的,并且是第一个参数(客户端指定的类型)那么这一行
t=:=typeOf[Boolean]
如何确定“[yn]”属于Boolean类型呢?@vasigorc,您可以将其用作
validateType[Boolean](“y”)
,在那里,为
T
设置泛型类型
Boolean
ClassTag
未弃用,您将其与
Manifest
@AlexeyRomanov混淆,谢谢澄清。
/@弃用(“使用scala.reflect.ClassTag(捕获擦除)或scala.reflect.runtime.universe.TypeTag(捕获类型)或两者兼而有之”,“2.10.0”)特征清单[T]扩展了类清单[T]
Hello@chengpohi,我给Cyrille的答案是正确的。您的方法确实消除了编译错误,但如果输入正确([YyNn])程序意外终止。这很有趣!内部的
def validate
是一个递归方法,因此为了编译它的返回类型必须是
Boolean
?并且我必须为任何新的返回类型声明一个隐式的返回类型?是的。很抱歉忘记了返回类型。谢谢@Cyrille Corpet。我正在更改答案正确,因为这不仅可以编译,还可以产生预期的行为。这很有趣!内部的
def validate
是一个递归方法,所以为了编译它的返回类型必须是
Boolean
?我必须为任何新的返回类型声明一个隐式?是的,非常抱歉tten返回类型。谢谢@Cyrille Corpet。我正在更改此项的正确答案,因为这不仅可以编译,还可以生成预期的行为。