【问题标题】:Scala, can't implement generic java methodScala,无法实现通用的java方法
【发布时间】:2012-07-28 05:19:44
【问题描述】:

我想在 scala (2.9.2) 中实现一个使用泛型的 java 方法。但我失败了……

Java接口方法:

public <T extends Number> void setAttribute(Key<T> key, Number value);

想要实现该方法的 Scala 代码:

def setAttribute[T <: Number](key: Key[T], value: Number) = {
  setAttributeLocal(key, value)  }

private def setAttributeLocal[T](key: Key[T], value: T) = {
  val stringValue = ConvertUtils.convert(value, classOf[String]).asInstanceOf[String]
  session = session + (key.getValue() -> stringValue)
}

键看起来像:

public class Key<T>

但这不能编译。

[error]  found   : mypackage.Key[T]
[error]  required: mypackage.Key[java.lang.Number]
[error] Note: T <: java.lang.Number, but Java-defined class Key is invariant in type T.
[error] You may wish to investigate a wildcard type such as `_ <: java.lang.Number`. (SLS 3.2.10)
[error]     setAttributeLocal(key, value)

我不知道是什么问题。有什么建议/想法吗?

好极了 加菲猫克隆

【问题讨论】:

  • 我们需要知道Key 的样子。因为如果我使用public interface Key&lt;T&gt;,上面的代码编译得很好。
  • @GarfieldKlon 您正在使用哪个版本的 scala?
  • @0__ 在哪个版本下编译?
  • @Richard Scala 2.9.1, 2.9.2, 2.10.0-M6 - 因为我不知道setAttributeLocal 会是什么,所以我没有尝试写那个我>。所以错误一定存在,因此问题需要包含该信息。
  • setAttributeLocal的类型签名是什么?

标签: java scala generics methods implements


【解决方案1】:

编译器似乎对您对setAttributeLocal 的调用不满意。 setAttributeLocal 需要 Key[Number],但您提供的是 Key[_ &lt;: T]。在 Java-Land 中,这意味着您正在尝试将 Key&lt;? extends Number&gt; 传递为 Key&lt;Number&gt;

建议让setAttributeLocal 接受Key&lt;? extends Number&gt;Key[_ &lt;: Number],具体取决于它是Java 还是Scala 定义的。

【讨论】:

  • @GarfieldKlon 我不得不读了几次......我认为 Ben 的建议是,如果你专注于修复 setAttribute,那么你可能看错了。您描述的错误是setLocalAttribute 的类型问题,而不是setAttribute。你对setLocalAttribute 的定义是怎样的?
  • @Richard - 好吧,这就解释了为什么我不能重现这个
  • 我们终于添加了这个解决方案:private def setAttributeLocal[T](key: Key[T], value: Object)
【解决方案2】:

这里看起来有点不对劲。

你试过了吗:

def setAttribute[T <: Number](key: Key[T], value: T) =
  setAttributeLocal(key, value)

为键保留类型 T 似乎很奇怪/不好,但不在值上使用它。我的猜测是你会得到一个不变的错误。您正在尝试将 Number 类型的值分配给 T 类型的键,并且编译器不确定它是否不能为 T 传递 Number(虽然它知道它可以传递 @987654326 @ 代表Number)。

我们能看到更多代码吗?

【讨论】:

  • 这不是一个选项,因为它不是覆盖。
  • Java 和 Scala 的类型接口存在限制。您在 Java 中所做的是类型不健全,因此 Scala 不允许这样做。如果您想继续使用该类型向导,那么您将不得不坚持使用 Java 的类型系统,抱歉。
【解决方案3】:

正如@jsuereth 已经指出的那样,setAttributesetAttributeLocal 的签名之间存在差异,即前者接受Key[T &lt;: Number],但将与密钥相关的值固定为@ 987654324@,而后者更灵活,允许 key 和 value 为T &lt;: Number。这看起来很奇怪,您可能需要重新考虑该决定。这也导致了@Ben Schulz 解释的问题。

无论如何,编译器 (2.9.1) 对以下设置很满意:

MyI.java:

public interface MyI {
  public <T extends Number> void setAttribute(Key<T> key, Number value);
}

Key.java:

public interface Key<T> {
}

Test.scala:

object Test extends App {
  def setAttribute[T <: Number](key: Key[T], value: Number) = {
    setAttributeLocal(key, value)  }

  private def setAttributeLocal[T](key: Key[T], value: Number) = {
    /* Notice that value is now also of type Number. */
  }
}

【讨论】:

    猜你喜欢
    • 2022-01-15
    • 2014-01-13
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多