Whenever we speak about Open-Closed Principle, one important issue comes into play, which is called Strategic Closure.
It should be clear that no significant program can be 100% closed. In general, no matter how “closed” a module is, there will always be some kind of change against which it is not closed. Since closure cannot be complete, it must be strategic. That is, the designer must choose the kinds of changes against which to close his design. This takes a certain amount of prescience derived from experience. The experienced designer knows the users and the industry well enough to judge the probability of different kinds of changes. He then makes sure that the open-closed principle is invoked for the most probable changes.
For example in famous sample of Shape class you just grantee that your program (in side of Client and Shape)just is closed for modification about adding new shape.
public class Shape {
public draw() {
}
}
public class Circle extends Shape {
@Override
public void draw() {
// implementation special to Circle
}
}
public class Client {
...
public drawMyShape(Shape shape) {
shape.draw();
}
...
}
According to this Strategy, when you are designing your program, you should make a decision about the sections that you want to be closed to changes. Therefore, in your example, when you were designing your program, if you decided that your entity (in this case it is GraphCalculator class) should be closed for modification and open to extension regarding to adding new functionality, adding new function in this example violates Open-Closed Principle, due to the fact that it changes implementation in side of client and GraphCalculator class. And solution can be using abstraction, which is mentioned in previous answers.