是否可以在 Scala 中编写一个方法,该方法返回具有不同类型参数的类型参数化类的对象?像这样的东西:
class A[T]
def f(switch: Boolean): A = if(switch) new A[Int] else new A[String]
请注意:上面的代码是虚构的,以显示问题的类型;上面的代码在语义上没有意义。
上面的代码不会编译,因为返回类型 A 没有参数化。
是否可以在 Scala 中编写一个方法,该方法返回具有不同类型参数的类型参数化类的对象?像这样的东西:
class A[T]
def f(switch: Boolean): A = if(switch) new A[Int] else new A[String]
请注意:上面的代码是虚构的,以显示问题的类型;上面的代码在语义上没有意义。
上面的代码不会编译,因为返回类型 A 没有参数化。
您可以,甚至可以借助封装配对的隐式参数来实现类型安全:
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()
您确实必须从布尔值显式映射到自定义True
和False
值。
(我选择List
作为目标类只是一个例子;你可以选择任何东西,甚至可以通过更多的工作使其通用。)
(编辑:正如 oxbow_lakes 指出的那样,如果您需要在同一代码路径上表示所有可能的返回值,那么仅此一项是行不通的,因为 and 的超类List[Int]
is List[String]
,List[Any]
这没有多大帮助。在这种情况下,您应该使用. 我的解决方案是针对仅在or上下文Either
中使用的单个函数,并且可以在那里维护类型信息。)True
False
表达这一点的一种方法是使用Either
;
def f(switch: Boolean) = if (switch) Left(new A[Int]) else Right(newA[String])
这当然会返回一个Either[A[Int], A[String]]
. 您当然不能(目前)声明一个返回一些参数化类型的方法P
,以及一些类型参数的子集(即只有 Int
or String
)。
锡兰语言具有联合类型,我理解其意图是在不久的将来将这些添加到 scala 中,在这种情况下,您可以定义一个方法:
def f(switch: Boolean): A[Int|String] = ...
好吧,你可以做这样的事情。
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
但这是没有意义的。类型是编译时信息,而该信息在这里丢失了。
对“虚构代码”进行绝对最小的更改怎么样?如果我们只是[_]
在“虚构”返回类型之后添加,代码将编译:
class A[T]
def f(switch: Boolean):A[_] = if(switch) new A[Int] else new A[String]
值得注意的A[_]
是不一样A[Any]
。A[T]
不需要为编译代码定义协变。不幸的是,有关类型的信息会丢失。