【问题标题】:def fn[String] seems to break Scala / java.lang.String compatibilitydef fn[String] 似乎破坏了 Scala / java.lang.String 的兼容性
【发布时间】:2012-04-05 12:00:52
【问题描述】:

你好,堆栈溢出,

我希望你能帮助我解决我的第一个问题:)

所以我遇到了 Scala 类型推断的问题。代码如下:

object Problem {

  def ok(fn: (String) => Unit) = fn("")

  // type mismatch; found: java.lang.String("") required: String
  def fail[String](fn: (String) => Unit) = fn("")

}

Scala 在这里期望什么样的字符串?

请注意,这是解释我的问题的最小示例。当我尝试实现更复杂的接口(确切地说是 Play 的 Iteratee)时,出现了最初的问题,所以,不,省略 [String] 不是一个选项。 (如果有人认为实际代码会有所帮助,我会提供。)

我试过def fail[java.lang.String] ...,但它显示expected ], found .

我确实阅读了Scala String vs java.lang.String - type inference,它很好地解释了java.lang.Stringscala.Predef.String,但我仍然无法针对我的具体问题提出解决方案。

有什么想法吗?

编辑:所以这是我尝试实现http://www.playframework.org/documentation/api/2.0/scala/play/api/libs/iteratee/Iteratee.html的最初尝试,只是我写了String而不是T。 (使用T 可以编译,这很有意义!)我的失败;显然我对所有类型参数有点不知所措:

val stream = WS.url("url").get({ headers =>
  (new Iteratee[Array[Byte], String] {
    def fold[T](done: (String, Input[Array[Byte]]) => Promise[T],
                cont: (Input[Array[Byte]] => Iteratee[Array[Byte], String]) => Promise[T],
                error: (String, Input[Array[Byte]]) => Promise[T]): Promise[T] =
    {
      done("something", Input.Empty)
    }
  })
})

问候, 亨德里克

【问题讨论】:

    标签: scala generics type-inference


    【解决方案1】:

    当你写作时:

    def fail[String](fn: (String) => Unit) = fn("")
    

    方括号String 之间的类型参数只是一个任意名称,在您的情况下,它将隐藏scala 或java 字符串。它完全等同于:

    def fail[T](fn: (T) => Unit) = fn("")
    

    如果你想将类型限制为字符串,你只需要写:

    def fail(fn: (String) => Unit) = fn("")
    

    它适用于 scala 和 java 字符串(因为它们是相同的)。

    【讨论】:

    • 谢谢,现在你说的很明显了... :|
    • 这个答案是正确的,尽管我选择了@submonoid's 来处理我实际上无法更改的方法签名。
    • @Hendrik - 据我所知,签名没有意义。为什么你不能改变它?签名必须是什么? (你会误会它必须是什么吗?)
    • 添加了上面的原始代码,应该可以解释我的误解。
    【解决方案2】:

    这个问题与 Java vs Scala 字符串无关。

    def fail[String](fn: (String) => Unit) = fn("") 行中,您定义了一个全新 类型参数并将其命名为String。这掩盖了一般定义。

    如果您打算对类型进行抽象,则需要类型参数。您在 fail 示例中没有这样做,应该删除它。

    如果您要覆盖使用类型参数的内容,则应在 class 级别指定:

    class A extends B[String]
    

    查看 Iteratee 的代码,我猜您正在尝试使用其各种 doneconterror 函数来实现 fold。 Fold 只有一个类型参数,用于返回类型,所以我不确定它来自哪里。输入类型参数是在类中指定的,因此如果您扩展Iteratee[String, Unit],则应提供这些参数。

    【讨论】:

    • 是的,我现在明白了 - 啊!对类型进行调度是一种有趣的方法。谢谢!
    • 这是一个很好的观点,我将删除它。抱歉,我的答案写得太快了。
    • 太糟糕了,看起来很有趣;(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-25
    • 1970-01-01
    • 1970-01-01
    • 2019-11-02
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    相关资源
    最近更新 更多