In response to my previous story, a commenter asked if the code I posted works due to a closure relationship rather than inheritance. The argument is that the field can be accessed by a nested class, and it wasn’t actually passed as a member to the other class. The reader of the story states that the field would still be accessed in Java even if Employee didn’t inherit from Person. Then, the question is asked if it’s different in C#.
I’m not familiar enough with Java to speak about how it works, but I can discuss what is happening in C#. First, let’s take a look at the code in question.
public class Person
{
private string message;
public override string ToString()
{
return message;
}
public static Person CreateEmployee()
{
return new Employee();
}
class Employee : Person
{
public Employee()
{
this.message = "I inherit private members!";
}
}
}
The reason you can be sure the constructor of Employee modifies the member named message on the instance of employee is because of the ‘this’ keyword. This keyword refers to the current instance, and this is the reason I don’t bother with underscores or funky names in my fields. If I need to scope to a member field, using the ‘this’ keyword is clearer than semantic customs… plus it has compiler support! Using ‘this’ within a nested type only refers to members of that type, and not the outer type
Of course, I use the keyword for convention, it oftentimes isn’t necessary. What happens If I remove the ‘this.’ from ‘this.message’?
public Employee()
{
message = "I inherit private members!";
}
It still compiles, but whereas the answer was clearly “it’s inheritance” before, the lack of the keyword brings lack of clarity. So what’s happening? We could bring it up in reflector, but it would be more fun to modify the code. Let’s actually strip the inheritance hierarchy. This will require a few other modifications.
public class Person
{
private string message;
public override string ToString()
{
return message;
}
public static Employee CreateEmployee()
{
return new Employee();
}
public class Employee
{
public Employee()
{
message = "I inherit private members!";
}
}
}
And we find out quickly enough that this is will not work. Despite the lack of ‘this’, message was referring to the private member on Employee. Since Employee no longer inherits from Person, it is trying to access the field in the outer class. This gives us a rare error message.
Cannot access a non-static member of outer type 'Person' via nested type 'Person.Employee'
There’s a very simple explanation for this. Employee has been nested inside of Person. Just because you have an instance of the nested type does not mean you will have an instance of the outer type. Nesting allows for interesting accessibility scenarios, but there is no other special relationship defined.
The accessibility relationship works like this. I can create a method inside of Employee to access a private member of Person.
public class Employee
{
public void Demo()
{
var person = new Person();
person.message = "accessed";
}
}
In the original version, it is possible to access the message field of Person from Employee if the message field is static as no instance is required.
I am not sure how this all works in Java, but my original example demonstrated inheritance with private accessibility. Try it out for yourself!