[英]Is it possible to write a method in Scala returning objects with different type parameter?
Is it possible to write a method in Scala which returns an object of a type-parameterized class with different type paramter ? 是否可以在Scala中编写一个方法,该方法返回具有不同类型参数的类型参数化类的对象? Something like this: 像这样的东西:
class A[T]
def f(switch: Boolean): A = if(switch) new A[Int] else new A[String]
Please note: The Code above is fictional to show the type of problem; 请注意:上面的代码是虚构的,以显示问题的类型; The code above does not make semantically sense. 上面的代码没有语义意义。
The code above will not compile because return type A is not parameterized. 上面的代码将无法编译,因为返回类型A未参数化。
You can, and you can even do it with type-safety with the aid of implicit arguments that encapsulate the pairings: 你可以,你甚至可以借助封装配对的隐式参数来实现类型安全:
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()
You do have to explicitly map from boolean values to the custom True
and False
values. 您必须显式地从布尔值映射到自定义的True
和False
值。
(I have chosen List
as the target class just as an example; you could pick anything or even make it generic with a little more work.) (我已经选择List
作为目标类作为一个例子;你可以选择任何东西,甚至可以通过更多的工作使它成为通用的。)
(Edit: as oxbow_lakes points out, if you need all possible return values to be represented on the same code path, then this alone won't do it, because the superclass of List[Int]
and List[String]
is List[Any]
, which isn't much help. In that case, you should use an Either
. My solution is for a single function that will be used only in the True
or False
contexts, and can maintain the type information there.) (编辑:正如oxbow_lakes所指出的,如果你需要在同一代码路径上表示所有可能的返回值,那么单独就不会这样做,因为List[Int]
和List[String]
的超类是List[Any]
,这是没有太大的帮助。在这种情况下,你应该使用的Either
。我的解决办法是将在只能用单一的功能True
或False
的上下文,并在那里保持类型的信息。)
One way of expressing this would be by using Either
; 表达这一点的一种方法是使用Either
;
def f(switch: Boolean) = if (switch) Left(new A[Int]) else Right(newA[String])
This of course returns an Either[A[Int], A[String]]
. 这当然会返回一个Either[A[Int], A[String]]
。 You certainly cannot (at the moment) declare a method which returns some parameterized type P
, with some subset of type parameters (ie only Int
or String
). 你当然不能(目前)声明一个方法,它返回一些参数化类型P
,带有一些类型参数的子集(即只有 Int
或 String
)。
The language ceylon has union types and I understand the intention is to add these to scala in the near future, in which case, you could define a method: 语言锡兰有联合类型,我理解的意图是在不久的将来将这些添加到scala,在这种情况下,您可以定义一个方法:
def f(switch: Boolean): A[Int|String] = ...
Well, you could do something like that. 好吧,你可以做那样的事情。
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
But this is pointless. 但这毫无意义。 Types are a compile time information, and that information is getting lost here. 类型是编译时信息,这些信息在这里丢失。
How about an absolutely minimal change to the "fictional code"? 对“虚构代码”进行绝对微小的改动怎么样? If we just add [_]
after the "fictional" return type, the code will compile: 如果我们只是在“虚构”返回类型之后添加[_]
,代码将编译:
class A[T]
def f(switch: Boolean):A[_] = if(switch) new A[Int] else new A[String]
It is worth noting that A[_]
is not the same as A[Any]
. 值得注意的是A[_]
与A[Any]
。 A[T]
does not need to be defined covariant for the code to compile. 对于要编译的代码,不需要为A[T]
定义协变。 Unfortunately, information about the type gets lost. 不幸的是,有关该类型的信息会丢失。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.