Preventing certain moves using ValueSelector results in ClassCastException.

huangapple go评论57阅读模式
英文:

Preventing certain moves using ValueSelector results in ClassCastException

问题

我有一个名为 Lecture 的类,其中包含一个 startTime 计划变量和一个固定的持续时间。我尝试筛选掉导致结束时间超过16:00的移动。

我已经编写了一个选择过滤器:

public class LectureOutOfBoundsSelectionFilter
        implements SelectionFilter< Schedule, Lecture > {

    @Override
    public boolean accept(ScoreDirector< Schedule > sd, Lecture lecture) {
        return !lecture.isOutOfBounds();
    }
}

我将其配置如下:

<changeMoveSelector>
    <filterClass>package.PinnedTimeslotChangeMoveFilter</filterClass>
    <valueSelector>
        <filterClass>packager.LectureOutOfBoundsSelectionFilter</filterClass>
    </valueSelector>
</changeMoveSelector>

但我遇到了与 Lecture 中不同计划变量相关的类转换异常。我尝试添加 variableName="startTime",但这触发了不同的类转换异常。

我是否在正确的方向上,variableName 属性实际上是如何工作的?

英文:

I have a Lecture class with a startTime planning variable and a fixed duration. I'm trying to filter out moves that causes the end time to go past 16:00.

I have written a selection filter:

public class LectureOutOfBoundsSelectionFilter
        implements SelectionFilter&lt;Schedule, Lecture&gt; {

    @Override
    public boolean accept(ScoreDirector&lt;Schedule&gt; sd, Lecture lecture) {
        return !lecture.isOutOfBounds();
    }
}

Which I configure as follows

&lt;changeMoveSelector&gt;
    &lt;filterClass&gt;package.PinnedTimeslotChangeMoveFilter&lt;/filterClass&gt;
    &lt;valueSelector&gt;
        &lt;filterClass&gt;packager.LectureOutOfBoundsSelectionFilter&lt;/filterClass&gt;
    &lt;/valueSelector&gt;
&lt;/changeMoveSelector&gt;

But I'm getting a class cast exception related to a different planning variable in Lecture. I've tried adding variableName=&quot;startTime&quot; but this triggers a different class cast exception.

Am I on the right track here, and how does the variableName attribute actually work?

答案1

得分: 1

I'll start off your additional comment, where you explain further:

> With variableName=&quot;startTime&quot; I'm getting java.lang.ClassCastException: class package.ImmutableTimeslot cannot be cast to class package.Lecture. Without variableName set, I get java.lang.ClassCastException: class package.Room cannot be cast to class package.Lecture.

There is an explanation for this behavior, although it is not really very intuitive:

  • 当您在值选择器上没有设置变量名时,两种变量类型都会传递到过滤器。在这种情况下,ImmutableTimeslotRoom。由于您的过滤器期望一个 Lecture,两者之一会引发异常。
  • 当您指定选择器的变量名为 startTime 时,这不再会触发对 room 变量值的值选择器;因此,您会得到 ImmutableTimeslotLecture 不匹配的异常。

在这两种情况下,问题似乎是您的过滤器期望 Lecture 实例(实体),但求解器发送的是 ImmutableTimeslotRoom(计划变量的值)。这可以说是选择器的正确行为(强调“值”这个词)。

我之所以称之为“不太直观”的原因有两个部分:

  • 无论应用于移动选择器、实体选择器还是值选择器,都始终需要相同的 SelectionFilter 接口。因此,根据您打算使用它的位置,所需的通用类型不同,这令人困惑(分别是移动、实体或值)。
  • 在多个变量的情况下(就像您的情况),如果在选择器上不指定 variableName,则泛型参数需要为 Object,因为该过滤器将接收两种类型的值,这是避免您遇到的异常的唯一方法。

总的来说,这不是最佳的设计;它来自2012年,由于保持向后兼容性并且我们实际上不鼓励使用选择过滤器,它一直没有改变,一直延续到现在。

英文:

I'll start off your additional comment, where you explain further:

> With variableName=&quot;startTime&quot; I'm getting java.lang.ClassCastException: class package.ImmutableTimeslot cannot be cast to class package.Lecture. Without variableName set, I get java.lang.ClassCastException: class package.Room cannot be cast to class package.Lecture.

There is an explanation for this behavior, although it is not really very intuitive:

  • When you put the filter on the value selector without a variable name, both variable types will reach the filter. In this case ImmutableTimeslot and Room. Since your filter expects a Lecture, either of the two throws the exception.
  • When you specify the selector's variable name to be startTime, this no longer triggers the value selector on values of the room variable; therefore, you are getting an exception where ImmutableTimeslot doesn't match Lecture.

In both cases, the problem appears to be that your filter is expecting Lecture instances (the entities), but the solver is sending either ImmutableTimeslot or Room (values of the planning variables). This is arguably the correct behavior of a value selector (emphasis on the word "value").

The reason why I'm calling this "not really intuitive" comes in two parts:

  • The same SelectionFilter interface is always required, regardless if applied to a move selector, an entity selector or a value selector. So, based on where you intend to use it, the generic type required is different and that is confusing. (A move, an entity or a value respectively.)
  • In cases with multiple variables (such as yours) without specifying a variableName on the selector, the generic parameter needs to be Object, because that filter will be receiving both types of values and that is the only way to avoid the exception you are getting.

All in all, not the best design; it comes from 2012 and due to maintaining backwards compatibility and us actually discouraging the use of selection filters, it has survived unchanged until the present day.

huangapple
  • 本文由 发表于 2023年3月31日 04:22:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75892687.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定