Scala泛型函数返回类型



我试着写一个泛型返回类型的函数,但它不工作,除非我转换返回类型。请参阅下面的函数getSomething(),我希望它在没有铸造的情况下工作。我在这里做错了什么?

trait Sup
class Sub extends Sup {
  def getString = "I am Sub"
}
class Sub2 extends Sup {
  def getInt = 100
}
def getSomething[A <: Sup](str: String) : A  = {
  str match {
    case "sub" => getSub.asInstanceOf[A]
    case "sub2" => getSub2.asInstanceOf[A]
  }
}
def getSub(): Sub = {
  new Sub
}
def getSub2() : Sub2 = {
  new Sub2
}
val x = getSomething[Sub]("sub").getString
val y = getSomething[Sub2]("sub2").getInt

正如Alexey提到的,需要instanceOf来强制在期望的类型和返回对象的类型之间建立链接。这相当于说:"编译器,相信我,我给你一个‘A’",这不是很安全,因为它依赖于我们提供正确的类型。

如果我们想让类型系统为我们解决问题,我们需要给它一些额外的信息。在Scala中实现这一点的一种方法是定义一些工厂,该工厂知道如何产生我们的类型的实例和证据,允许该工厂返回我们的特定类型。

这是上面代码的一个版本,引入了这样的结构,并使用ContextBounds来获得我们想要的类型的正确工厂实例。

trait Sup 
class Sub extends Sup {
  val str = "I'm a Sub"
}
class Sub2 extends Sup {
  val number = 42
}
trait SupProvider[T <: Sup] {
  def instance:T
}
object SupProvider {
  def getSomeSup[T<:Sup:SupProvider]: T = implicitly[SupProvider[T]].instance
  implicit object SubProvider extends SupProvider[Sub] {
    def instance = new Sub
  }
  implicit object Sub2Provider extends SupProvider[Sub2] {
    def instance = new Sub2
  }  
}
SupProvider.getSomeSup[Sub].str
// res: String = I'm a Sub
SupProvider.getSomeSup[Sub2].number
// res: Int = 42

没有asInstanceOf的错误消息确切地告诉您做错了什么。在case "sub"中,主体给出了Sub,编译器没有理由认为ASub的超类型(或者Sub可以隐式转换为A)。

假设它成功了。那么以下调用将是合法的:

val z = getSomething[Sub]("sub2").getString

trait Sub3 extends Sup
val w = getSomething[Sub3]("sup")

在这两种情况下应该发生什么?

相关内容

  • 没有找到相关文章

最新更新