我正在利用空闲时间自学计算机科学,目前正在上伯克利大学的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;
}
}因此,我没有任何方法将参数复制到Solver构造函数。如果程序使用初始WorldState调用求解器,然后更改该WorldState,则求解器解决方案也将反映更改,因为它持有对传入的对象的引用。我找到的解决方案通过让求解器明确地将包中的WorldState实现作为参数来解决这个问题,这样他们就可以创建一个该类型的新对象,并将参数复制到其中。但是赋值应该保持Solver类中的通用性。
我想做的一件事是创建一个WolrdState的实现,作为Solver的一个子类,它接受一个整型estimatedDistanceToGoal和迭代邻居变量作为参数,然后接口方法的实现将直接返回这些值。然而,我没有让它工作,因为赋值的其他部分将WorldState对象重新转换为一个特定的实现(板级),该实现作为初始arg传入,它在这里中断。这也将是一大笔开销。
还有没有其他的想法或方法可以给我指明正确的方向?谢谢你的帮助!
发布于 2019-01-28 01:41:04
WorldState实现也应该是不可变的。赋值告诉您创建一个名为Board的实现WorldState的不可变类。
如果不是这样,您仍然可以通过克隆作为参数传递给构造函数的WorldState,并将存储它的属性声明为final和private,从而使求解器不可变。
请记住,如果您希望对象是不可变的,则对象的状态不能被更改,但您可以构造一个具有您想要的更改的新对象。文档很好地example了可变类和不可变类之间的区别,这些类在功能上基本上没有区别。
发布于 2019-01-28 01:52:24
不可变类意味着一旦对象被创建,我们就不能改变它的内容。
我可以看到,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,那么它就可以被视为不可变的。
https://stackoverflow.com/questions/54390298
复制相似问题