mercoledì 28 settembre 2011

Do not be public!

This is a well known rule of the OOP: encapsulate!
What this really means is that, as in all computer science fields, you should start giving no-rights and then adding a few allowance. In other words, each property you declare in a class should be private, each method should be final/const and so on. Of course I'm excluding the struct-alike objects from this paradigm.
Why be so reluctant to use protected? Well, you will be able to give up your rights later, and to convert your private field to protected, or even to public. You will be able to give others the capability to overload your methods, but if you don't have a real need to allow them to, don't!
Consider the following example:

     public class Foo{
         protected int counter = 0;
       
        public void sendEmail(){ // do stuff }

        public Foo(){
               counter = 10;
               sendEmail();
        }
     }


What is wrong with this kind of code? A lot of things... First of all the counter variable can be accessed directly from Foo subclasses, and this could not be what you want. Imagine you want to assure that all instances of Foo (and of its subclasses) have a counter that is initialized to 10, how can you impose this? You have to declare counter as private and provide no setter method for it. Leaving the field protected is a call for troubles.
A worst error in the above code is the sendEmail method signature, which is not final, and therefore can be overriden. Why is this wrong? Because the constructor of Foo will call a polymorphic method, and trust me, this can lead you to endless debugging sessions!
Summarizing, I can say that you should declare everything private, and when it is not private, declare at least final, and only when you are sure of what are you doing, allow direct access to methods/fields.
Now consider what happens with C++ with regard to methods: each method declared not virtual is automatically declared as final in Java. In other words, C++ does it right: it gives you the stricter behaviour on methods. I agree with you when you say that having to write "virtual" for each method is an extra-typing that can be avoided, but it is the only way to avoid awkward errors and is a good way to prevent you to release an API that is broken.

Nessun commento: