Scala:返回传入类型的实例
我正在尝试实现一个简单的验证器方法,它需要 一个类型作为第一个参数,一个字符串作为第二个参数,并且总是返回传入类型的实例。无需进一步ado-这是一种方法: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
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。我正在更改此项的正确答案,因为这不仅可以编译,还可以生成预期的行为。