One base-class implementation changes the private fields directly:The completed operation leaves the area unchanged. It calls no overriding setters, so the logging subclass's count stays unchanged and does not need an override. The invariant is about completed public updates, not transient internal states between the two assignments.
def flip(): Unit = {
val oldH = _h
_h = _w
_w = oldH
}A second implementation uses public setters:These setter calls use dynamic dispatch on a logging receiver. Starting at height two and width three, the first call increases the temporary area from six to nine and wrongly increments the count, while the final area returns to six. This version needs a subclass override. With the counter name from part (i), the following override discards the internal setter contributions:For this specified base implementation the two assignments complete normally and the final area equals the initial area, so restoring the saved count is correct. Another design could suppress logging during the compound operation. The difference between the two base implementations illustrates the fragile base class problem: an internal refactoring can change subclass behavior through newly introduced virtual calls.
def flip(): Unit = {
val oldH = height
val oldW = width
height = oldW
width = oldH
}override def flip(): Unit = {
val before = increases
super.flip()
increases = before
} Articles by others on the same topic
There are currently no matching articles.