加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 如何根据类型参数的类型参数编写具有多态返回类型的函

发布时间:2020-12-16 08:59:56 所属栏目:安全 来源:网络整理
导读:我有一些像这样的代码: sealed trait Foo[A] { def value: A}case class StringFoo(value: String) extends Foo[String]case class IntFoo(value: Int) extends Foo[Int] 我想有一个函数可以使用给定子类型参数的A类型. // Hypothetical invocationval i: I
我有一些像这样的代码:

sealed trait Foo[A] {
  def value: A
}
case class StringFoo(value: String) extends Foo[String]
case class IntFoo(value: Int) extends Foo[Int]

我想有一个函数可以使用给定子类型参数的A类型.

// Hypothetical invocation
val i: Int = dostuff[IntFoo](param)
val s: String = dostuff[StringFoo](param)

我无法弄清楚如何以一种有效的方式声明dostuff.我能弄清楚的最接近的事情是

def dostuff[B <: Foo[A]](p: Param): A

但这不起作用,因为A在该位置未定义.我可以做点什么

def dostuff[A,B <: Foo[A]](p: Param): A

但是我必须像dostuff [String,StringFoo](param)一样调用它,这非常难看.

看起来编译器应该具有将A移动到返回类型所需的所有信息,如何在标准scala或库中进行此工作.我现在正在使用scala 2.10,如果这会影响答案.如果有可能的话,我只对2.11的解决方案持开放态度2.11

解决方法

您可能知道,如果您有一个类型为Foo [A]的参数,那么您可以在A中使该方法通用:

def dostuff[A](p: Foo[A]): A = ???

由于情况可能并非总是如此,我们可以尝试使用可以表达A和B之间关系的隐式参数.因为我们不仅可以将一些通用参数应用于方法调用(泛型参数推断是全部或者什么都没有),我们必须把它分成2个电话.这是一个选项:

case class Stuff[B <: Foo[_]]() {
    def get[A](p: Param)(implicit ev: B => Foo[A]): A = ???
}

您可以检查REPL中的类型:

:t Stuff[IntFoo].get(new Param) //Int
:t Stuff[StringFoo].get(new Param) //String

沿着相同的行,但使用匿名类的另一个选项是:

def stuff[B <: Foo[_]] = new { 
    def apply[A](p: Param)(implicit ev: B <:< Foo[A]): A = ??? 
}

:t stuff[IntFoo](new Param) //Int

在这里,我使用了apply而不是get,所以你可以更自然地应用这个方法.此外,正如您的评论中所建议的,我在这里使用了<:<在证据类型.对于那些希望了解更多有关此类广义类型约束的人,??您可以阅读更多here.

您也可以考虑使用抽象类型成员而不是通用参数.在努力使用泛型类型推理时,这通常会提供一种优雅的解决方案.您可以阅读有关抽象类型成员及其与泛型here的关系的更多信息.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读