private and static methods (also class instance member, no matter what access modifier it has) are "early binding" at compile time. Other methods are "late binding" and calls to these methods are resolved at run time, which enables the so called "Polymorphism".
In your code, R.printS1()is a private method, so it is binded at compile time. R.printS2() is protected, so "Polymorphism" is applicable.
When you invoke s.printS1S2(), R.printS1S2() is invoked. It then invoke printS1()which is binded to R.printS1() at compile time, and invoke S.printS2() due to
Polymorphism.
That's it. Hope it helps, mate.