在Scala中将字符串作为泛型函数或函数调用进行求值
我想编写一个通用函数在Scala中将字符串作为泛型函数或函数调用进行求值,scala,generics,pattern-matching,Scala,Generics,Pattern Matching,我想编写一个通用函数functionChooser,它将根据字符串参数从几个选项中选择要使用的函数 这项工作: def a (arg: String) = arg + " with a" def b (arg: String) = arg + " with b" def c (arg: String) = arg + " with c" def functionChooser(func: String, additionalArg: String) = { val f = func m
functionChooser
,它将根据字符串参数从几个选项中选择要使用的函数
这项工作:
def a (arg: String) = arg + " with a"
def b (arg: String) = arg + " with b"
def c (arg: String) = arg + " with c"
def functionChooser(func: String, additionalArg: String) = {
val f = func match {
case "a" => a _
case "b" => b _
case _ => c _
}
f(additionalArg)
}
scala> functionChooser("a", "foo")
res18: String = foo with a
我在使functionChooser
泛型时遇到问题,例如,当函数a
、b
和c
返回不同的案例类时:
case class A(s: String)
case class B(s: String)
case class C(s: String)
def a (arg: String) = A(arg)
def b (arg: String) = B(arg)
def c (arg: String) = C(arg)
//functionChooser def as before
scala> functionChooser("a", "foo")
res19: Product with Serializable = A(foo)
我不太明白我得到了什么,我知道调用functionChooser(“a”,“foo”).s时出错(“错误:值s不是可序列化的产品的成员”)
最后,我真正想要的是函数将返回这些案例类的列表,例如:
def a (arg: String) = List(A(arg))
def b (arg: String) = List(B(arg))
def c (arg: String) = List(C(arg))
因此functionChooser
应该是List[T]
的泛型,其中T
是某个类。您应该为所有三个函数返回上公共类型。对象(AnyRef)始终适合
def functionChooser(func: String, additionalArg: String) : AnyRef = {
在您的情况下,如果所有可能的返回值都是列表,您可以使用更具体的类型:
def functionChooser(func: String, additionalArg: String) : List[_] = {
当然,这将消除类型信息。任何方法都应该返回相同的类型,它不能是多态的。因此,您需要进一步使用.asInstanceOf[T]
case来获取此信息
这是有道理的,因为实际类型在运行时是未知的。e、 g.调度器字符串可由用户输入。若它在编译时是已知的,那个么您可以只使用适当的方法而不引用描述性字符串
如果您想为所有可能的返回类型获得一些共同的行为,那么您应该为它们定义一个共同的特征,并为其放置共同的方法。您应该为所有三个函数返回较高的共同类型。对象(AnyRef)始终适合
def functionChooser(func: String, additionalArg: String) : AnyRef = {
在您的情况下,如果所有可能的返回值都是列表,您可以使用更具体的类型:
def functionChooser(func: String, additionalArg: String) : List[_] = {
当然,这将消除类型信息。任何方法都应该返回相同的类型,它不能是多态的。因此,您需要进一步使用.asInstanceOf[T]
case来获取此信息
这是有道理的,因为实际类型在运行时是未知的。e、 g.调度器字符串可由用户输入。若它在编译时是已知的,那个么您可以只使用适当的方法而不引用描述性字符串
如果您想获得所有可能返回类型的一些常见行为,那么您应该为它们定义一个共同特征,并为其放置共同的方法。函数functionChooser
将返回案例类a
、B
和C
中最具体的通用超类型。由于案例类继承自Product
和Serializable
,因此常见的超类型是Product with Serializable
如果要访问案例类字段s
,则必须通过模式匹配强制转换结果,或者提供所有类a
、B
和C
的公共基类,以便访问该字段
特征库{
def s:字符串
}
案例类别A(s:String)扩展了基础
案例类别B(s:String)扩展了基础
案例类C(s:String)扩展了基础
使用此类型定义,functionChooser
的返回类型将是Product,可与Base一起序列化
,因此,结果将允许您访问s
如果您的函数a
、b
和c
返回各自案例类的列表
,则functionChooser
的返回类型将是列表[可与Base序列化的产品]
更新
如果无法更改类层次结构,则必须强制转换结果,或者可以在functionChooser
中提取必要的信息,并将其包装为另一种类型,其中包含所需的所有数据的超集。例如
def functionChooser(func: String, additionalArg: String): String = {
val f = func match {
case "a" => (a _).s
case "b" => (b _).s
case _ => (c _).s
}
f(additionalArg)
}
注意:这里我只提取字段s
,它是所有必需信息的超集。函数functionChooser
将返回案例类A
、B
和C
的最具体的通用超类型。由于案例类继承自Product
和Serializable
,因此常见的超类型是Product with Serializable
如果要访问案例类字段s
,则必须通过模式匹配强制转换结果,或者提供所有类a
、B
和C
的公共基类,以便访问该字段
特征库{
def s:字符串
}
案例类别A(s:String)扩展了基础
案例类别B(s:String)扩展了基础
案例类C(s:String)扩展了基础
使用此类型定义,functionChooser
的返回类型将是Product,可与Base一起序列化
,因此,结果将允许您访问s
如果您的函数a
、b
和c
返回各自案例类的列表
,则functionChooser
的返回类型将是列表[可与Base序列化的产品]
更新
如果无法更改类层次结构,则必须强制转换结果,或者可以在functionChooser
中提取必要的信息,并将其包装为另一种类型,其中包含所需的所有数据的超集。例如
def functionChooser(func: String, additionalArg: String): String = {
val f = func match {
case "a" => (a _).s
case "b" => (b _).s
case _ => (c _).s
}
f(additionalArg)
}
注意:这里我只提取字段s
,它是所有必需信息的超集。不做我想做的事,因为functionChooser(“a”,“foo”)。s
我仍然会得到错误:值s不是AnyRef
的成员。这是不可避免的,实际结果类型在编译器timentastic中是未知的,您的.asInstanceOf
编辑完成了工作。谢谢对于functionChooser(“a”,“foo”).s
I,不执行我想要的操作