Fabulous Adventures In Coding

Eric Lippert's Blog

Why Can't I Access A Protected Member From A Derived Class?

A question I got recently was about access to protected methods from a derived class. Clearly that's what "protected" means – that you can access it from a derived class. In that case, why doesn't this work?

class Ungulate {
  protected void Eat() { /* whatever */ }
}

class Giraffe : Ungulate {
  public static void FeedThem() {
    Giraffe g1 = new Giraffe();
    Ungulate g2 = new Giraffe();
    g1.Eat(); // fine
    g2.Eat(); // compile-time error "Cannot access protected member"
  }
}

What the heck? Giraffe is derived from Ungulate, so why can't it always call the protected method?

To understand, you have to think like the compiler. The compiler can only reason from the static type information, not from the fact that we know that at runtime g2 actually will be a Giraffe. For all the compiler knows from the static type analysis, what we've actually got here is

class Ungulate {
  protected virtual void Eat() { /* whatever */ }
}

class Zebra : Ungulate {
  protected override void Eat() { /* whatever */ }
}

class Giraffe : Ungulate {
  public static void FeedThem() {
    Giraffe g1 = new Giraffe();
    Ungulate g2 = new Zebra();
    g1.Eat(); // fine
    g2.Eat(); // compile-time error "Cannot access protected member"
  }
}

We can call Ungulate.Eat legally from Giraffe, but we can't call the protected method Zebra.Eat from anything except Zebra or a subclass of Zebra. Since the compiler cannot determine from the static analysis that we are not in this illegal situation, it must flag it as being illegal.

Incidentally, C++ has the same rule.

Published Wednesday, November 09, 2005 2:20 PM by Eric Lippert
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

Paulo Morgado said:

The compiler surelly knows that it's in a Ungulate derived class. So, the rule could be another one.
Nevertheless, the rule makes sense to me.
November 10, 2005 3:42 AM
 

Erno said:

I think that the real problem is that the FeedThem method is in the wrong class. As soon as you put FeedThem in the right place you will not need the construction you just created.
November 10, 2005 4:00 AM
 

Eric Lippert said:

But being in an ungulate-derived class is in this example not enough information to guarantee that you are in a derived class of the RUN TIME type of the callee.

Really what you're saying is that "protected" could be redefined to mean something weaker, such as "callable from any class derived from the base class which declares the protected method".

But that's not the kind of protection we've chosen as interesting or valuable. "Sibling" classes do _not_ get to be friendly with each other because otherwise protection is very little protection.
November 10, 2005 9:26 AM
 

Abhijit said:

I am not sure how this figures but I tried your example on JVM out of curiosity and it worked without any errors. This is what I used -
public class Mammal {
protected void Eat() {
System.out.println("In Mammal.eat()");
}
}
public class Giraffe extends Mammal {
public static void FeedThem() {
Giraffe g1 = new Giraffe();
Mammal g2 = new Giraffe();
g1.Eat(); // fine
g2.Eat(); // fine
}
public static void main(String[] args) {
Giraffe.FeedThem();
}
}

This might sound like a dumb question but if what you have shown is specific to C# then what is the rationale behind having such checking?
November 17, 2005 1:04 AM
 

Eric Lippert said:

I've only ever written one program in Java and that was about ten years ago, so I'm a bad person to ask about Java semantics.

However, my reading of section 6.6.2 of my 1996 copy of the JLS is that in your example, the semantics of "protected" do not apply because the two classes are in the same package.

If you read section 6.6.7, it describes the semantics of cross-package access to protected members via subclasses as being the same as I describe above.

Apparently in Java, "protected" means roughly what "Protected Friend" means in Visual Basic.
November 23, 2005 5:14 PM
 

Fabulous Adventures In Coding said:

This is a follow-up to my 2005 post on the same subject which I believe sets a personal record for the

March 28, 2008 7:30 PM
 

Frederik Siekmann said:

Well.

While this doesn't compile:

class Ungulate {

 protected void Eat() { /* whatever */ }

}

class Giraffe : Ungulate {

 public static void FeedThem() {

   Giraffe g1 = new Giraffe();

   Ungulate g2 = new Giraffe();

   g1.Eat(); // fine

   g2.Eat(); // compile-time error "Cannot access protected member"

 }

}

Making a subtile change (adding internal):

class Ungulate {

 protected internal void Eat() { /* whatever */ }

}

class Giraffe : Ungulate {

 public static void FeedThem() {

   Giraffe g1 = new Giraffe();

   Ungulate g2 = new Giraffe();

   g1.Eat(); // fine

   g2.Eat(); // compile-time error "Cannot access protected member"

 }

}

Tadaa: this will compile ... and I am really happy about that ... please don't fix this bug ;)

March 30, 2008 4:02 AM
 

Eric Lippert said:

That's not a bug. I'll be writing about that feature in my blog next week.

March 30, 2008 4:23 AM
 

Jesse said:

But the compiler's static type analysis can't detect this situation:

class RoboGiraffe : Giraffe {

 protected override void Eat() { /* use dangerous lasers that only RoboGiraffe is trained for */ }

}

Now when we say g1.Eat(), we may be calling RoboGiraffe.Eat, which should only be accessible from RoboGiraffe and its subclasses, right? Shouldn't that be prohibited under the very same logic that prevents us from calling Zebra.Eat?

December 14, 2009 6:40 PM

Leave a Comment

(required) 
(optional)
(required) 

  
Enter Code Here: Required
Submit

About Eric Lippert

Eric Lippert is a senior developer on the Microsoft C# compiler team. Before that he worked on the framework of Visual Studio Tools For Office. Before that, he worked on the compilers, runtimes and tools for VBScript, JScript, Windows Script Host and other Microsoft Scripting technologies. He lives in Seattle and spends his free time editing books about programming languages, playing the piano, and trying to keep his tiny sailboat upright in Puget Sound.

This Blog

Syndication


© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker