有没有办法从scala中的单个方法返回不同的返回类型?
例如,如果我有一个load()
方法,我想根据调用此方法的对象返回不同的数据类型。
def load(path: String):<return type>
{
// if this instance is of type "type1", do some processing on this object,
// and return object of type "type1"
// else if this instance is of type "type2", do some processing on this object,
// and return object of type return "type2"
}
答案 0 :(得分:4)
如果我理解你想要的是什么,F-bounded polymorphism可能适合你:
trait Base[T <: Base[T]] {
def load(path: String): T
}
class Type1 extends Base[Type1] {
override def load(path: String): Type1 = new Type1 // provisional implementation
}
class Type2 extends Base[Type2] {
override def load(path: String): Type2 = new Type2
}
然后load
将返回当前对象的类型。请注意这些表达式中的结果类型:
new Type1().load(path)
scala> res2: Type1 = Type1@744f0e0b
new Type2().load(path)
scala> res3: Type2 = Type2@77988c45
答案 1 :(得分:1)
您可以使用scala&#39; Either
:
def load(path : String) : Either[Type1, Type2] = {
this match {
case t1 : Type1 => Left(someProcessing(t1))
case t2 : Type2 => Right(someOtherProcessing(t2))
}
}
答案 2 :(得分:0)
正如其他人所说,你可以使用
您可以使用scala的Either
请记住,调用方法的每个方法都需要检查它返回的类型(使用.map
或模式匹配)。通常使用Either[ErrorType, NormalType]
btw,但当然你可以随意使用
scala cats library还有其他选择:http://eed3si9n.com/herding-cats/Xor.html
当然,scalaz还提供了另一种选择:http://appliedscala.com/blog/2016/scalaz-disjunctions/
作为最后的手段,你不能定义自己的“Either”
答案 3 :(得分:0)
如果您的要求就像返回上下文实例类型的某个实例一样简单...即this
那么您可以这样做,
class A() {
def omg(s: String): this.type = new A()
}
如果涉及遗产,
trait A {
type omgType
def omg(s: String): omgType
}
class B() extends A {
override type omgType = this.type
override def omg(s: String): omgType = new B()
}
class C() extends A {
override type omgType = this.type
override def omg(s: String): omgType = new C()
}
但是如果你想要更多的一般性,那么你可能想要阅读以下内容并将其应用于那里,
最简单的方法是从喷雾中大量使用的magnet pattern
中获取灵感。
我们可以利用灵感来构建我们的自定义解决方案,记住它既不是pure magnet pattern
也不是path dependent type
方法。它是两者的黑巧克力。
所以...让我们假设您希望def process
能够支持Int
和String
类型的输入参数,最后返回相应的结果。
您需要为这些类型定义隐式磁铁,
trait ProcessMagnet {
type Input
type Result
def input: Input
def process: Result
}
object ProcessMagnetProvider {
implicit def stringToStringProcessMagnet(string: String): ProcessMagnet = new ProcessMagnet {
override type Input = String
override type Result = String
override def input: Input = string
// define this for your doing...
override def process: Result = input + "_omg"
}
//... add for all your inputs
implicit def intToIntProcessMagnet(int: Int): ProcessMagnet = new ProcessMagnet {
override type Input = Int
override type Result = Int
override def input: Input = int
// define this for your doing...
override def process: Result = input + 1
}
}
def process[T](t: T)(implicit pmConverter: T => ProcessMagnet): ProcessMagnet = pmConverter(t)
// now just import our implicit magnets...
import ProcessMagnetProvider._
val intResult: Int = process(5).process.asInstanceOf[Int]
val stringResult: String = process("omg").process.asInstanceOf[String]
答案 4 :(得分:0)
工厂方法怎么样,只是定义特征loadable
,例如:
trait Loadable {
def load(path: String): Loadable
}
class Type1 extends Loadable {
def load(path: String): Type1 = this
}
class Type2 extends Loadable {
def load(path: String): Type2 = this
}
object Main {
def test(): Loadable = {
new Type1().load("path")
}
def main(args: Array[String]): Unit = {
println(test().getClass)
}
}