janv. 30

By chance, I have discovered something new related to the protected keyword yesterday. I was very surprised because I had never seen such a behavior in C++ or Java. But maybe I had never tested it in the past ? Anyway, I think it's important enough to share it with you.

Private keyword

Just for reminding, a private member will be visible only in the container object (class or structure). However, you can write something like :

public class ClassWithPrivate
{
   private int privateMember;
 
   public void DoSomething(ClassWithPrivate c)
   {
      /* The private members are also accessible on 
       * another instance, as long as you work with it
       * inside of the class */
      c.privateMember = 12;
   }
}

Protected keyword

With the previous example shown, we can expect a similar behavior with the protected keyword as it is an "extended private". Indeed a protected member will be visible in the container object and also in all the derived class of this object. However, there is a limitation when working with other instances as shown below:

public class BaseClass
{
   protected void DoSomething() { }
}
 
public class DerivedClass : BaseClass
{
   public void OtherMethod()
   {
      //The protected method of the base class is accessible on "this"
      this.DoSomething();
 
      //The protected method is accessible via another instance
      DerivedClass derived = new DerivedClass();
      derived.DoSomething();
 
      /* Compilation Error:
       * Cannot access protected member 'BaseClass.DoSomething()' 
       * via a qualifier of type * 'BaseClass'; the qualifier 
       * must be of type 'DerivedClass' (or derived from it)
       */
      BaseClass baseClass = new DerivedClass();
      baseClass.DoSomething();
   }
}

Experts of all language, can you tell me if you have this limitation also in your language ?

Extra question : I don't really see why we have this compilation error. Why this limitation exist ? DO you have any idea or clue ?

Tags: | | | |

Commentaires

Thierry Thoua

Posted on mercredi, 30 janvier 2008 13:43

I've the same limitation in C++. For .net, it's written in the ECMA-334 but they aren't explicit about the reason ... (and I don't know why :/)

pe.dautreppe

Posted on mercredi, 30 janvier 2008 19:19

I'm waiting for our C++ master that may light our darkness on. Didier are you there ? Wink

For info, where have you seen that in the ECMA ? related to the protected keyword ? I'll have a look to it.

Thierry Thoua

Posted on mercredi, 30 janvier 2008 23:29

http://en.csharp-online.net/ECMA-334:_10.5.3_Protected_access_for_instance_members

Didier Pieroux

Posted on mardi, 5 février 2008 15:57

The C++ behavior is similar to the C# one. To the contrary, Java is more permissive and allows the access.

I believe that there is no "technical reason" for this "limitation" (since it is always possible to render visible any field by making it public), but a language choice.

In C++, a derived object may access the protected members of its base class only through a derived object. The derived class has no special access to the protected members of base type objects [Lippman, 15.2.2].

I guess that the C# rule is similar (*). The second sentence makes the intent of the rule crystal-clear: if a BaseClass is used as a class of its own, its privacy has to be enforced against other classes, including from classes that are derived from it. The privacy must only be dropped-off for the BaseClass part of DerivedClass instances.

To the contrary, Java is more relax and allows DerivedClass instances to access protected members of any BaseClass instances. This means that Java weakens the encapsulation principle, which is bad from a pure OO point of view. But on the other side, it makes the access rule a bit simpler to understand, which is good too and is compatible with the principle of least astonishment ;)

Hope this help...
DP

(*) I can't access the link given by Thierry from here, so I can't check the C# rule.

Damien Pinauldt

Posted on mardi, 5 février 2008 22:16

Just to put my salt :
object, ie System.Object, defines at least one protected method :
object MemberwiseClone(), which by default makes a shallow copy of the current instance.

If protected methods where accessible for all derived classes, anybody (as anybody inherits object) could call .MemberwiseClone().

Btw, did you know that System.Object wasn't the really base class ?
At least, if I believe the Reflector (Lutz Roeder's must-have), object overrides a Finalize() method.
So "someone" should declare a virtual or abstract Finalize() method, no ?
I really need to configure this symbol server I've so heard about :
http://tinyurl.com/yqsokg

Laurent Bossavit

Posted on lundi, 11 février 2008 01:31

If the compiler allowed this:

  BaseClass baseClass = new DerivedClass();
  baseClass.DoSomething();

then, since it has no way to distinguish the two, it would also have to allow the following:

  BaseClass baseClass = new OtherDerivedClass();
  baseClass.DoSomething();

where OtherDerivedClass is a different class derived from BaseClass (but not from DerivedClass).

However, to do so would violate the semantics of "protected", which dictates that visibility is restricted to derived classes of the method's owner.

DerivedClass is *not* derived from OtherDerivedClass, so it has no business invoking a protected method on an instance of that class. Therefore the compiler cannot allow the first formulation.

Ajouter un commentaire




biuquote
  • Commentaire
  • Aperçu immédiat
Loading