Reputation: 1077
I'm coming from a long period of programming in Java
.
I'm solving a coding problem and trying to write an abstract solution class that will be extended by three classes:
var isValidSudoku = function(board) {
return new CheckRows(board).isValid()
// && checkCols(board)
// && checkBoxes(board);
};
class AbstractSolver {
constructor(board) {
this._board = board;
this._numSet = new Set();
this._state = {
x: 0,
y: 0,
}
}
getCell() {
const numString = this._board[this._state.y][this._state.x];
return isNumBetween0And9(numString) ?
{
isNum: true,
num: parseInt(numString, 10),
} :
{
isNum: false,
};
}
nextCell() {}
nextBlock() {}
isBlockFinish() {}
isBoardFinish() {}
isValid() {
while (this.isBoardFinish() == false) {
while (this.isBlockFinish() == false) {
const {
isNum,
num,
} = this.getCell();
if (isNum == false) {
// do nothing
} else if (this._numSet.has(num)) {
return false;
} else {
this._numSet.add(num);
}
this.nextCell();
}
this.numSet.clear();
this.nextBlock();
}
return true;
}
}
function check(a) {
return f => f(a);
}
function isNumBetween0And9(i) {
const checkNum = check(i);
return checkNum(Number.isInteger) && checkNum(x => x >= 0) && checkNum(x => x <= 9);
}
class CheckRows extends AbstractSolver {
constructor(board) {
super(board);
this._boardLen = 9;
}
nextCell() {
this._state = {
x: this._state.x + 1,
y: this._state.y,
};
}
nextBlock() {
this._state = {
x: 0,
y: this._state.y + 1,
};
}
isBlockFinish() {
this._state.x >= this._boardLen;
}
isBoardFinish() {
this._state.x >= this._boardLen && this.state.y >= this._boardLen;
}
}
const testParam = [
["5", "3", ".", ".", "7", ".", ".", ".", "."],
["6", ".", ".", "1", "9", "5", ".", ".", "."],
[".", "9", "8", ".", ".", ".", ".", "6", "."],
["8", ".", ".", ".", "6", ".", ".", ".", "3"],
["4", ".", ".", "8", ".", "3", ".", ".", "1"],
["7", ".", ".", ".", "2", ".", ".", ".", "6"],
[".", "6", ".", ".", ".", ".", "2", "8", "."],
[".", ".", ".", "4", "1", "9", ".", ".", "5"],
[".", ".", ".", ".", "8", ".", ".", "7", "9"]
];
const testParam2 = [
["5", "3", "3", ".", "7", ".", ".", ".", "."],
["6", ".", ".", "1", "9", "5", ".", ".", "."],
[".", "9", "8", ".", ".", ".", ".", "6", "."],
["8", ".", ".", ".", "6", ".", ".", ".", "3"],
["4", ".", ".", "8", ".", "3", ".", ".", "1"],
["7", ".", ".", ".", "2", ".", ".", ".", "6"],
[".", "6", ".", ".", ".", ".", "2", "8", "."],
[".", ".", ".", "4", "1", "9", ".", ".", "5"],
[".", ".", ".", ".", "8", ".", ".", "7", "9"]
];
console.log(isValidSudoku(testParam2));
The problem is, when the method isValid
of class
CheckRows
runs, It invokes the method isValid
of AbstractSolver
which runs Its method isValid
and invokes all the unimplemented "abstract" methods of the super class instead of invoking the overridden methods of the sub-class. This would have worked in Java
. Is there a way to fix It in JS
? And more importantly: Is there a better best practice?
Upvotes: 0
Views: 38
Reputation: 1074266
The problem isn't that the wrong methods get called (the right ones do), the problem is that the methods don't return a value. Just like in Java, you need the return
keyword to return a value from a method:
isBlockFinish() {
return this._state.x >= this._boardLen;
//^^^^^^
}
isBoardFinish() {
return this._state.x >= this._boardLen && this.state.y >= this._boardLen;
//^^^^^^
}
Arrow functions have an implicit return if you use a concise function body (for example, () => value
), but methods don't.
There are further problems after that (numSet
instead of _numSet
, an index going out of range), but that's the problem that (presumably) made you think the abstract methods rather than the overridden ones were being called.
Upvotes: 2