The No.1 i-Technology Magazine in the World !
   
 

      ES no BS
This is a personal blog of Yakov Fain       My son's animations and music         No BS IT podcast      Америчка




Archives

««Aug 2010»»
SMTWTFS
1234567
891011121314
15161718192021
22232425262728
293031

RSS Feed








Subscribe to these blogs

Who needs protected variables?

posted Friday, 25 August 2006
For years, object-oriented programmers knew that one of the main OOP features is encapsulation: an ability to hide and protect object internals. Private and protected properties were invented to support  this.  But who are we hiding from? From stupid developers who will decide to use our smart framework classes.

In some OOP languages only descendent classes can access protected variables from the ancestor.  Java relaxed this rule a little bit and allows accessing protected  variables from classes located in the same package.  Recently, I had to extend a class from a particular third party framework, which had a protected variable defined. My class was not located in the same package as that third party component...  Let's look at this example.

The code below works fine:

public class Father {
   protected int abc = 25;
}

public class Son extends Father{
   public Son (){
    System.out.println("abc=" + abc);
   }
}

public class MyNewClass {
    public static void main(String[] args) {
         Son son = new Son();
         System.out.println("Son.abc="+ son.abc);
    }
}

The MyNewClasss is happily printing
abc=25
Son.abc=25

Now  move the Father and Son to the package com.thirdparty.framework.
After adding the import com.thirdparty.framework.*; to MyNewClass, the code still does not compile complaining that son.abc is not visible. Of course, because designers of the third party framework wanted to protect their precious abc variable, and they wanted to force me to inherit MyNewClass from their Father or Son.. Did they achieve their goal?  Not at all.  They just forced me to create a Grandson in my default package with a public getter to the abc property.

import com.thirdparty.framework.Son;
public class Grandson extends Son {
   public int getAbc(){
       return abc;
   }
}

And MyNewClass now looks as follows:

public class MyNewClass {
         public static void main(String[] args) {
         Grandson grandson = new Grandson();
         System.out.println("Grandson.abc="+ grandson.getAbc());
    }
}

It’s just annoying that I need to add the GrandSon because designers of the third party framework decided to make the abc protected.

If you want to restrict the access to a property, make it private and give me a public getter, if needed. If you want to let everyone work with a property, make it public.

But who needs  this protected access level?

tags:      

links: digg this    del.icio.us    technorati    




1. Igor G left...
Saturday, 26 August 2006 12:13 am

I guess that protected valiable could be useful when you do not want to expose it in public interface, but want to allow access to these variables from subclasses...


2. Yakov Fain left...
Saturday, 26 August 2006 6:38 am

Igor,

This is a book answer, and I know this much :) I'm looking for a real world use cases when having a protected (vs. private with a public getter/setter) can be useful

I've asked the same question at Javalobby and so far no one can give me an answer. See http://www.javalobby.org/java/forums/t77911.html


3. Igor G left...
Saturday, 26 August 2006 2:08 pm

Yakov,

I did not mean to give a book answer ( knowing that you wrote some books :) ), it just occurred to me that this is one of these cases where book definition is very close to practical use.

Below is my real life example:

public abstract class GenericTestCase extends junit.framework.TestCase {

  • protected org.apache.commons.logging.Log log;

  • public static String DATA_DIR_PROPERTY="data.dir";

  • private org.w3c.dom.Document doc = null;

  • protected GenericTestCase( String name ) {

super(name);
  • Class c = this.getClass();

  • log = org.apache.commons.logging.LogFactory.getLog ( c );

setDocument( c );

  • }

  • protected void setDocument (Class c){

    • ...

  • }

  • protected org.w3c.dom.Document getDocument() { return doc; }

  • protected String getTestFieldStringFromCDATA(String fieldName, org.w3c.dom.Node testNode) throws Exception {

    • ...

  • }

    • protected String getTestFieldString(String fieldName , org.w3c.dom.Node testNode ) {

      • ...

    • }

  • protected Object[] getTestFieldArray ( String fieldName, org.w3c.dom.Node testNode) throws Exception {

  • ...

  • }

}

In this case log is protected because only subclasses of GenericTest should using "log", and not other instances. Other Tests would have their own Log instances. It actually becomes a problem if they use it because Log name will be different for each subclass and logger would output incorrect info. One other practical advantage that comes to my mind is IDE feature, where content assist might not present protected methods outside of GenericTestCase subclasses

I guess you did not talked about methods in your post, but there are also "getTestField..." protected methods in my class

When this class was created I asked myself, would I need to use these methods and log and "getTestField..." methods outside of unit test classes? answer was no, so I made it protected.

I would not go into philosophical and theoretical discussions about "to be" or "not to be" for protected variables/methods, but I have used it in real life projects and consider it useful. I also think that in example that you provide it was more about your experience with specific framework rather where design decision would make big role why framework designers choose to use protected members the way you describe.

Regards,

Igor.


4. Yakov Fain left...
Saturday, 26 August 2006 8:32 pm

Would it be bad it your GenericTestCase had the variable log private and a public getLog() method? You've asked yourself if anyone else would need use getTestField, and answered negative. Do you even have aske yourself this question?

What if your IgorTestCase that extends GenericTestCase is a really useful class for my application as well? Since you designed is as protected, YakovTestCase can not use it directly. Now, I'll need to create a subclass in your package IgorSonTestCase with public getIgorTestField that will be a simple wrapper around the superclass's getTextField. I'll call the getTextField anyway, but the code becomes more convoluted


5. Igor G left...
Monday, 28 August 2006 9:08 am

Yakov,

It looks to me that you and I approaching this use case differently - you prefer not to have this level of protection, where something is shared within calss hierarchy, because you need to use it from outside classes. I am as a designer on the other hand prefer to hide these class members, which could be done for many reasons - I like to have fine grained structure to help me organize my class members better or these methods are wrappers already and I would hide it form users of my class, I want for other classes to have their own logs, and there could be more things.

But if we put this use case on the wieght of advanatages vs disadvantages, I think that using protected in this specific case is justified -

Advantages:

1. just by using protected accees to log is restricted from other classes. 2. access to getTestField() method protected, which prevent users from using unwanted functionality. 3. When I create superclasses, I prefer to hide protected members in IDE editor.

Disadvantages:

1. it is not clear why method is hidden, therefore code needs to be looked for similar methods if any or wrapper class created. For example there are XMLUtility class that does basic XML operations that used inside getTestField()

Anyway, I would love to go for lunch with you sometime to discuss it further..... :)

Regards,

Igor.


6. Yakov Fain left...
Monday, 28 August 2006 9:18 am

Lunch is fine, but during lunch I'd rather talk about food, travel, wine, beer and women than about use of protected variables :)


7. Michael V left...
Monday, 28 August 2006 9:50 pm

Yakov,

An interesting question! It was fun to think of an answer..

First, the question is formulated incorrectly. A private variable with a public getter has nothing to do with a protected variable: the former denotes a read-only attribute, whereas the latter is actually a public (!) attribute.

It is well known that a protected interface of a class does not differ much from a public one: just like the latter, it cannot be easily changed as soon as it published. So the only difference is a possibility to express the <i>intent</i> of the design:

1. If the stupid users of my framework want to assess this variable/method, I'd like to make their life as hard as possible.

2. I hope the smart users of my framework would understand why I made it protected rather than public..

Hope this helps. ;)

Thanks, Michael


8. Yakov Fain left...
Monday, 28 August 2006 10:01 pm

Sorry Michael, it did not help.

First, do not be picky. Private variables can have both: getters and setters. So I (a stupid user) could have changed your smart protected variable by adding a setter to this subclass.

You just made a statement that smart users of your framework will understand why you made it protected rather than public. But are you sure You understand yourself why you made it protected? So who's the stupid here?

Hope this helps :)


9. Michael V left...
Monday, 28 August 2006 10:27 pm

I meant that defining "protected" vs. public is just a concise way to communicate a message:

Hey, guys, this variable/method should have been private! But accessing it in a sub-class can make that sub-class more effective, or useful, so I am publishing it here. If you make public getter/setter in your sub-class, it is your choice, but then it will be your design, not mine.

Of course, the "protected" access modifier can be safely removed from a programming language, and the above message added as a comment, if desired.

Thanks, Michael