是否可以在Scala中编写一个返回具有不同类型参数的对象的方法?

时间:2012-06-25 15:24:32

标签: scala type-parameter

是否可以在Scala中编写一个方法,该方法返回具有不同类型参数的类型参数化类的对象?像这样:

class A[T]

def f(switch: Boolean): A = if(switch) new A[Int] else new A[String]

请注意:上面的代码是虚构的,以显示问题的类型;上面的代码没有语义意义。

上面的代码无法编译,因为返回类型A未参数化。

4 个答案:

答案 0 :(得分:6)

你可以,你甚至可以借助封装配对的隐式参数来实现类型安全:

class TypeMapping[+A,B] {
  def newListB = List.empty[B]
}
trait Logical
object True extends Logical
object False extends Logical

implicit val mapFalseToInt = new TypeMapping[False.type,Int]
implicit val mapTrueToString = new TypeMapping[True.type,String]

def f[A <: Logical,B](switch: A)(implicit tmap: TypeMapping[A,B]) = tmap.newListB

scala> f(True)
res2: List[String] = List()

scala> f(False)
res3: List[Int] = List()

您必须从布尔值显式映射到自定义TrueFalse值。

(我已选择List作为目标类作为示例;您可以选择任何内容,甚至可以通过更多工作使其成为通用。)

(编辑:正如oxbow_lakes所指出的,如果你需要在同一个代码路径上表示所有可能的返回值,那么单独这样做就不会这样做,因为List[Int]和{{1}的超类} List[String],这没有多大帮助。在这种情况下,您应该使用List[Any]。我的解决方案是针对单个函数,仅在Either或{ {1}}上下文,并可以在那里维护类型信息。)

答案 1 :(得分:4)

表达此信息的一种方法是使用Either;

def f(switch: Boolean) = if (switch) Left(new A[Int]) else Right(newA[String])

这当然会返回Either[A[Int], A[String]]。你当然不能(目前)声明一个方法,它返回一些参数化类型P,带有一些类型参数子集(即 Int String)。

语言锡兰有联合类型,我理解的目的是在不久的将来将这些添加到scala,在这种情况下,你可以定义一个方法:< / p>

def f(switch: Boolean): A[Int|String] = ...

答案 2 :(得分:0)

嗯,你可以这样做。

scala> class A {
     |   type T
     | }
defined class A

scala> def f(b: Boolean): A = if(b) new A { type T = Int } else new A { type T = String }
f: (b: Boolean)A

但这毫无意义。类型是编译时信息,这些信息在这里丢失。

答案 3 :(得分:-1)

“虚构代码”的绝对最小变化怎么样?如果我们只是在“虚构”返回类型之后添加[_],代码将编译:

class A[T]
def f(switch: Boolean):A[_] = if(switch) new A[Int] else new A[String]

值得注意的是A[_]A[Any]不同。 A[T]不需要为编译代码定义协变。 不幸的是,有关该类型的信息会丢失。