在String中将String评估为通用函数或函数调用

时间:2015-09-30 14:19:16

标签: scala generics pattern-matching

我想编写一个泛型函数functionChooser,它将根据String参数从几个选项中选择使用哪个函数。

这有效:

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通用邮件方面遇到了麻烦,例如当函数abc返回不同的案例类时:

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(" error: value s is not a member of Product with Serializable")时出现错误。

最后,我真正想要的是函数将返回这些案例类的列表,例如:

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是某个类。

2 个答案:

答案 0 :(得分:4)

函数functionChooser将返回案例类ABC中最具体的常见超类型。由于案例类继承自ProductSerializable,因此常见的超类型为Product with Serializable

如果要访问案例类字段s,您必须通过模式匹配来转换结果,或者提供所有类A的公共基类,{{1} }和B,允许您访问该字段。

C

使用此类型定义,trait Base { def s: String } case class A(s: String) extends Base case class B(s: String) extends Base case class C(s: String) extends Base 的返回类型为functionChooser,因此,结果将允许您访问Product with Serializable with Base

如果您的函数sab返回相应案例类的c,那么List的返回类型将是{{ 1}}。

更新

如果您无法更改类层次结构,则必须转换结果,或者您可以在functionChooser中提取必要的信息,并将其包含在另一种类型中,该类型包含您需要的所有数据的超级集合。 E.g。

List[Product with Serializable with Base]

注意:这里我只提取字段functionChooser,它是所有必需信息的超级集合。

答案 1 :(得分:1)

您应该返回所有三个函数的上部公共类型。对象(AnyRef)始终适合。

def functionChooser(func: String, additionalArg: String) : AnyRef = {

在您的情况下,所有可能的返回值都是列表,您可以使用更具体的类型:

def functionChooser(func: String, additionalArg: String) : List[_] = {

当然,这将消除类型信息。任何方法都应该返回相同的类型,它不能是多态的。因此,您需要进一步使用.asInstanceOf[T]案例,以获取此信息。

这是有道理的,因为实际类型在运行时是未知的。例如调度程序字符串可以由用户输入。如果在编译期间知道它,那么您可以使用适当的方法而不引用描述性字符串。

如果您希望获得所有可能返回类型的一些常见行为,那么您应该为它们定义一个共同特征并为其设置常用方法。