Today I faced
scala.MatchedError: 0 (of class java.lang.Integer)
in overridden
renderComponent
method of
scala.swing.Table
, when I tried to add rows.
val table = new Table(0, 2) {
override protected def rendererComponent(sel: Boolean, foc: Boolean, row: Int, col: Int): Component = {
col match {
case 1 => tcr.componentFor(this, sel, foc, "bar", row, col)
}
}
}
It turned out that I need a match for all possible values. In this particular case for 0, because I have two columns. So adding undermentioned code solved the problem
case 0 => super.rendererComponent(sel, foc, row, col)
At the beginning I was confused by the error message and thought that there might be some casting problem. So I tried to store 1 into value
val table = new Table(0, 2) {
override protected def rendererComponent(sel: Boolean, foc: Boolean, row: Int, col: Int): Component = {
val columnIndex: Int = 1
col match {
case columnIndex => tcr.componentFor(this, sel, foc, "bar", row, col)
}
}
}
Ta-dah! Program compiles, adding rows to table works, it seemed that I fixed the problem, but in fact I just made one of the most common mistakes that Scala beginners do. It is the second time when I fall into this trap, that is why I chose to mention about it on my blog.
In this situation
columnIndex
inside match is not the same
columnIndex
that was defined in first line of the function. It is variable initialized with
col
value. As there is no condition check just an assignment, the expression to the right of the arrow is always executed and each column contains component that I only wanted to appear in second one.
To fix this issue I need to use
stable identifier, which in Scala must either start with uppercase letter
val table = new Table(0, 2) {
override protected def rendererComponent(sel: Boolean, foc: Boolean, row: Int, col: Int): Component = {
val ColumnIndex: Int = 1
col match {
case ColumnIndex => tcr.componentFor(this, sel, foc, "bar", row, col)
}
}
}
or be surrounded by backticks
val table = new Table(0, 2) {
override protected def rendererComponent(sel: Boolean, foc: Boolean, row: Int, col: Int): Component = {
val columnIndex: Int = 1
col match {
case `columnIndex` => tcr.componentFor(this, sel, foc, "bar", row, col)
}
}
}
The first solution seems to be much better as it is agreeable with Scala's naming convention, according to which constants names should start with capital letter.
Please notice that you cannot define
columnIndex
as variable. Changing
val
to
var
in last two snippets will produce compile error.