As a library developer, you can explicitly declare all your methods as overridable. The key point is that in large scale software development, in Java, you can have the following undesirable situation:
Version 1, you import a third party library:
public class ThirdParty
{
public void calculateAndPrintResult()
{
System.out.println("1");
}
}
public class Mine extends ThirdParty
{
public void calculateAndPrintResult()
{
super.calculateAndPrintResult();
this.printResult();
}
protected void printResult()
{
System.out.println("2");
}
public static void main(String[] arguments)
{
Mine mine = new Mine();
mine.calculateAndPrintResult();
// Prints 1, 2
}
}
Version 2, third party has refactored and introduced printResult. You swap in the new third party library and suddenly the behavior has changed:
public class ThirdParty
{
public void calculateAndPrintResult()
{
this.printResult();
}
protected void printResult()
{
System.out.println("1");
}
}
public class Mine extends ThirdParty
{
public void calculateAndPrintResult()
{
super.calculateAndPrintResult();
this.printResult();
}
protected void printResult()
{
System.out.println("2");
}
public static void main(String[] arguments)
{
Mine mine = new Mine();
mine.calculateAndPrintResult();
// Prints 2 ! (wrong)
}
}
While this example is trivial, bear in mind, when you have programming in the large, i.e. large codebases with a lot of third party libraries and many teams of developers, you would rather not have surprises like this pulled on you, or you pulling surprises like this on other people.
It can take a lot of work tracking down this kind of bug.
When you finally realize this type of issue arises despite everyone following "best practice" OOP, then the reason is because "best practice" OOP is not actually best practice.