我在业余时间自学计算机科学,目前正在参加伯克利的CS61B课程,该课程在线发布了材料。我本人已经能够弄清大部分事情,但在作业上却只停留在一点上。规范在这里:https://sp18.datastructur.es/materials/hw/hw4/hw4
挑战在于Solver类应该是不可变的。 Solver类具有以下API:
public class Solver {
public Solver(WorldState initial)
public int moves()
public Iterable<WorldState> solution()
}
WorldState是一个接口,而不是一个类,如下所示:
package hw4.puzzle;
public interface WorldState {
/** Provides an estimate of the number of moves to reach the goal.
* Must be less than or equal to the correct distance. */
int estimatedDistanceToGoal();
/** Provides an iterable of all the neighbors of this WorldState. */
Iterable<WorldState> neighbors();
/** Estimates the distance to the goal. Must be less than or equal
* to the actual (and unknown) distance. */
default public boolean isGoal() {
return estimatedDistanceToGoal() == 0;
}
}
因此,我无法将参数复制到规划求解构造函数。如果程序使用初始的WorldState调用求解器,然后更改该WorldState,则Solver解决方案也将反映该更改,因为它拥有对传入对象的引用。我能够通过专门设计Solver来解决此问题。将包中WorldState的实现作为参数,以便他们可以创建该类型的新对象并将参数复制到该对象。但是该分配应该在Solver类中保持通用性。
我试图做的一件事是创建一个WolrdState实现,作为Solver的子类,该继承器将int EstimatedDistanceToGoal和Iterable邻居变量作为参数,然后接口方法的实现将直接返回这些值。但是,我没有使它起作用,因为分配的其他部分将WorldState对象重铸为作为初始arg传入的特定实现(Board),并在此处中断。这也将是一大笔开销。
还有其他任何想法或方法可以指引我正确的方向吗?我知道该课程旨在合理地防止解决方案在线泄漏,因此,也许PM响应会更合适,或者只是提示而不是解决方案。谢谢您的帮助!
答案 0 :(得分:0)
WorldState实现也应该是不变的。作业将告诉您创建一个名为Board的不变类,该类实现WorldState。
如果不是这种情况,您仍然可以通过克隆传递给构造函数的参数WorldState来使Solver不可变,并声明将其存储为final和private的属性。
请记住,如果您希望对象的状态不变,则不能对其进行更改,但是可以构造一个具有所需更改的新对象。 example文档很好地说明了可变类和不可变类之间的差异,而功能上基本上没有差异。
答案 1 :(得分:0)
不可变的类意味着一旦创建了对象,我们将无法更改 其内容。
我可以看到,WorldState
实现是不可变的,因为它仅包含getter或计算。因此,您只需要将此引用保存到
public final class Solver {
private final WorldState initial;
public Solver(WorldState initial) {
this.initial = initial;
}
public int moves() {
// should not modify internal state; only calculation
}
public Iterable<WorldState> solution() {
// should not modify internal state; only calculation
}
}
最后,如果Solver
类不更改其状态和所有变量的状态,例如initial
,则可以将其视为不可变的。