【问题标题】:Implementing methods having raw types in Scala在 Scala 中实现具有原始类型的方法
【发布时间】:2011-03-11 22:43:10
【问题描述】:

我在 Scala 中使用 Drools Planner(用 Java 编写)时遇到问题。 Drools 规划器中的接口之一声明为:

public interface Score<S extends Score> extends Comparable<S>

但是另一个接口使用'Score'作为原始类型:

public interface Solution {
    Score getScore();

那我想在 Scala 中实现这个接口:

class MySolution extends Solution {
    def getScore: Score = ...

我得到一个编译错误:Scala 编译器不允许只写 'def getScore: Score'。当我尝试添加 'Score[_]' 或 'Score[whatever]' 时,编译器会抱怨类型不兼容。我该怎么办?

【问题讨论】:

  • 能否把类型兼容性错误的全文也贴出来?
  • 有趣的案例。 Adam Warski 在用户邮件列表上也发布了类似的问题。我们应该在 Drools Planner 源代码中解决这个问题。我创建了这个问题来跟踪它:issues.jboss.org/browse/JBRULES-2924
  • 谢谢。但是,我也希望 Scala 对此提供一些支持。 Drools Planner 可能不是唯一存在此问题的库。
  • Drools Planner 的开发者应该修复他们的代码。甚至 Sun/Oracle 也做蠢事的相关示例:lampsvn.epfl.ch/trac/scala/ticket/3634

标签: java scala drools drools-planner


【解决方案1】:

编写一个 Java 类作为 Java 接口要求和 Scala 允许的接口之间的桥梁。

SolutionBridge.java:

abstract class SolutionBridge implements Solution {
    public Score getScore() {
        return scalaGetScore();
    }

    abstract Score<?> scalaGetScore();
}

SolutionScala.scala:

class SolutionScala extends SolutionBridge {
    def scalaGetScore() = null.asInstanceOf[Score[_]]
}

【讨论】:

  • 是的,我也有类似的想法,但它需要 Java。我更喜欢直接在 Scala 中执行此操作。
  • @iirekm 是的,好吧,没有这样的运气。请注意,原始类型属于 最后一个要 EOLed 的 Java 版本中。 Java 1.4 不在 Scala 支持的 JVM 版本中。
【解决方案2】:

您省略的错误消息不是无关紧要的细节。关于“我也希望 Scala 对此提供一些支持”,您也可以选择通过阅读错误消息来参与该过程,如果您不理解它们,请在提问时将它们包括在内,而不是模糊地解释它们。

错误消息,它们很重要。即使他们感到困惑。尤其是当他们感到困惑时。

这是 2.8.1 中的错误:

a.scala:2: error: overriding method getScore in trait Solution of type ()Score[_ <: Score];
 method getScore has incompatible type
  def getScore: Score[_] = null
      ^
one error found

这是中继的错误:

a.scala:2: error: overriding method getScore in trait Solution of type ()Score[_ <: AnyRef];
 method getScore has incompatible type
  def getScore: Score[_] = null
      ^
one error found

那里有一个关键的区别,这就是为什么当我按照错误消息的指示这样做时它与主干一起工作的原因。

// this compiles with 2.9, but not with 2.8
class MySolution extends Solution {
  def getScore: Score[_ <: AnyRef] = null
}

在 Java 源代码中使用原始类型 Score 的方式(在一个位置作为类型构造函数,但在另一个位置具有隐含的存在类型参数,第二个外观限制第一个外观)它可以在任何地方工作,这是一个奇迹。您不想知道适应这种事情已经对编译器造成了多大的损害。确实,如果原始类型可以正常工作会很好,但很多事情都会很好。有些事情是不可能的,有些事情是不可取的,有些事情需要少数人付出太多的努力才能让船继续航行。原始类型赢得三冠王。

【讨论】:

  • 这种损害称为向后兼容性。是的,这并不容易,但有必要让 Scala 得到更广泛的采用。
  • 甚至 Java 都无法提供您想要的向后兼容性。 Sun/Oracle 宣布在 Java 的未来版本中可能会放弃对原始类型的支持。 Scala 并不是为了重蹈 Java 犯下的所有错误而构建的。
【解决方案3】:

Drools Planner (5.2.0.M2) 的下一个版本将是fix this issueHere's the commit on git.

在某些情况下,人们希望定义自己的 Score 实现(例如 NurseRosterScore 实现 HardAndSoftScore),以便能够向用户显示每个硬约束或软约束类型究竟违反了什么解决方案。此更改是使这更容易和更清洁的第一步(即使它已经成为可能)。

【讨论】:

  • 非常感谢。有空我试试。
【解决方案4】:

你试过投Score:

val s = solution.getScore.asInstanceOf[Score[Int]]

【讨论】:

  • 这不是问题:我还没有“解决方案”对象。当我尝试实现“MySolution extends Solution”时遇到这个问题
猜你喜欢
  • 1970-01-01
  • 2020-02-25
  • 1970-01-01
  • 1970-01-01
  • 2017-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多