7

我在 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]' 时,编译器会抱怨类型不兼容。我应该怎么办?

4

4 回答 4

9

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

解决方案Bridge.java:

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

    abstract Score<?> scalaGetScore();
}

解决方案Scala.scala:

class SolutionScala extends SolutionBridge {
    def scalaGetScore() = null.asInstanceOf[Score[_]]
}
于 2011-03-11T23:06:28.557 回答
4

您省略的错误消息不是无关的细节。关于“我也希望 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 的方式(在一个位置作为类型构造函数,但在另一个位置具有隐含的存在类型参数,第二个外观限制第一个),它可以在任何地方工作,这是一个奇迹。您不想知道适应这种事情已经对编译器造成了多大的损害。确实,如果原始类型可以正常工作会很好,但很多事情都会很好。有些事情是不可能的,有些事情是不可取的,有些事情需要少数人付出太多的努力才能让船继续航行。原始类型赢得三冠王。

于 2011-03-13T03:43:12.973 回答
3

Drools Planner的下一个版本(5.2.0.M2)将解决这个问题这是 git 上的提交。

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

于 2011-03-13T12:27:30.833 回答
0

您是否尝试过投射Score

val s = solution.getScore.asInstanceOf[Score[Int]]
于 2011-03-11T22:50:02.180 回答