2

I have the following simple C# code, but I do not understand the output.

using System; namespace ConsoleApplication4 { class myParent { public int id = 3; private string name = "Parent class private string"; public void mymethod() { Console.WriteLine("{0} & {1}", name, id); } } class myChild : myParent { private string name = "Child class private string"; } class Program { static void Main(string[] args) { myChild c1 = new myChild(); c1.mymethod(); Console.ReadLine(); } //Output //Parent class private string & 3 } } 

When I invoke c1.mymethod(), why is string name in the myParent class used instead of string name in myChild class since I am invoking a method on myChild object which has a defined string name variable?

I used to believe that inheritance means simply virtually copying and pasting code from a base class to a derived class to reuse code or save key stroke. But after some research, this doesn't seem to be the case. Invoking a inherited method somehow references the base class, which might explains the output in my code.

However, I am still not clear about the inner working of inheritance. For example, I never created an instance of the base class. How should the base class method ( myParent.mymethod() ) exit?

Please help clarity my confusion and point me to some documentations.

7
  • There is already an answer to your question here Commented Feb 5, 2017 at 15:11
  • 4
    Possible duplicate of Are private members inherited in C#? Commented Feb 5, 2017 at 15:14
  • 1
    runtime Polymorphism does not apply to fields regardless of whether they are private or not. Commented Feb 5, 2017 at 15:16
  • Thanks for the link. Most intro level tutorials dont make the distinction between accessiblity and inheritance when it comes to private fields. Commented Feb 5, 2017 at 15:35
  • 1
    What do you mean "I never created an instance of the base class"? When a cow is born, a mammal is born, i.e. the cow. Commented Feb 5, 2017 at 15:52

6 Answers 6

3

Private is the most restrictive access for a field. It means that no other class has access to it, only the current one. Each class has its own set of private fields.

The reason why your application behaves like this is because your mymethod() member is declared public. That means that any class can call it. Since you are inheriting it, you automatically get that method in myParent. It is not copied into myparent, it is inherited. And since it is not overridden by myChild a call to myChild.mymethod() will invoke it on myParent, which accesses the only private name field it can (the one inside myParent).

If you want to inherit the name field, so it will act more like you are expecting, you need to make the field protected instead of private.

class myParent { public int id = 3; protected string name = "Parent class private string"; public void mymethod() { Console.WriteLine("{0} & {1}", name, id); } } class myChild : myParent { public myChild() { name = "Child class private string"; } } 

Now the variable in myParent is overwritten by myChild when it is instantiated. So, when you make a call to myChild.mymethod() it has access to the new value.

Sign up to request clarification or add additional context in comments.

7 Comments

If you want to inherit the name field, so it will act more like you are expecting, you need to make the field protected instead of private.. That sounds misleading. You will also need to override the method which you already mentioned but the statement is misleading on its own.
@CKing no, making the field protected and setting the field in the child's c.tor is enough: you don't need to override the method, look also at my answer, I'm saying the same thing
@user1892538 What I was trying to say is that simply making the field protected in the base class and leaving the rest of the code as-is will not work.
So a base class/object never actually "owns" what it inherits? It can only use the inherited members which will result in referrencing the base class?
Should be "derived clasd" in my last comment.
|
0

When I invoke c1.mymethod(), why is string name in the myParent class used instead of string name in myChild class since I am invoking a method on myChild object which has a defined string name variable?

The method c1.mymethod() is defined only in myParent class. Therefore, when you invoke the method, it is going to use the name found in closest proximity to that method. In other words, it will first search the myParent class for that variable and if found it will use it.

If you did this however (make myMethod virtual and override it in the myChild):

class myParent { public int id = 3; private string name = "Parent class private string"; public virtual void mymethod() { Console.WriteLine("{0} & {1}", name, id); } } class myChild : myParent { private string name = "Child class private string"; public override void mymethod() { Console.WriteLine("{0} & {1}", name, id); } } 

Then it will use the name variable from myChild class since that is the closest one.

You will run into a similar situation if you did this:

public class Person { private string name = "John"; public Person(string name) { // The parameter is named `name` and the field is named `name` // so the compiler is going to choose the closest variable. // In this case, it will assign `name` parameter to itself. // Visual Studio is nice, in this case, to give you a warning but // your code will compile and the compiler will just assign `name` // to `name` name = name; // If you did this: this.name = name; // then the private field will be assigned the value of the parameter } } 

4 Comments

If the base class private field is not found for the method, the compile will NOT use derived class private field because it is simply an entirely different field?
If it is not found in your base class then you will not even be able to compile your base class because your base class has no idea if someone will derive from it or not and it needs the field for the method.
Ha, that makes sense. Thanks
Do you need any more clarity or have I answered your question?
0

From C# specification:

Here is how Inhertiance is defined:

Inheritance means that a class implicitly contains all members of its direct base class type, except for the instance constructors, destructors and static constructors of the base class.

Now about extending base class.

A derived class extends its direct base class. A derived class can add new members to those it inherits, but it cannot remove the definition of an inherited member.

In other word you can extended base class by adding new definitions (or overriding existing ones), but you can't remove any.

And to get it more cleaner:

A derived class can hide (§3.7.1.2) inherited members by declaring new members with the same name or signature. Note however that hiding an inherited member does not remove that member—it merely makes that member inaccessible directly through the derived class.

What you do in your derived class is called hiding and as you can see from quote it doesnt remove that member.

And because in your MyParent class you are using name field defined in same class it will always print what it does. For changing this behaviour you should have look at Virtual properties.

2 Comments

Is it posible to hide a private member?
@JohnSmithSr. - I would say no, since by definition, a private member is hidden to all other classes but the current one. I private member cannot be hidden because it already is hidden.
0

Your new field name in the myChild class does not make the inherited field name from the base class go away! It just hides in. OK, it was hidden already because it was private, but introducing a new field in the derived class still does not make the hidden field go away.

If you want a name that is read-only, you can use a protected virtual property with no set accessor, and override it in the deriving class:

class myParent { public int id = 3; protected virtual string name => "Parent class private string"; public void mymethod() { Console.WriteLine("{0} & {1}", name, id); } } class myChild : myParent { protected override string name => "Child class private string"; } 

If you want to keep it as a private field, offer a constructor that the deriving class can chain:

class myParent { public int id = 3; private string name; public myParent() : this("Parent class private string") { } protected myParent(string name) { this.name = name; } public void mymethod() { Console.WriteLine("{0} & {1}", name, id); } } class myChild : myParent { public myChild() : base("Child class private string") { } } 

1 Comment

My first example is with name being a property which I also wrote. It is a valid example. Of course a field cannot be virtual, I agree.
0

This happens because you have used a method inside the parent's context. As you have not overridden myMethod() it will get executed using the private field in that parent's context. if you use method overriding here when you want to get the name of the child's context you can create a child object.

namespace ConsoleApplication2 { class myParent { public int id = 3; private string name = "Parent class private string"; public void mymethod() { Console.WriteLine("{0} & {1}", name, id); } } class myChild : myParent { private string name = "Child class private string"; public new void mymethod() { Console.WriteLine("{0} & {1}", name, id); } } class Program { static void Main(string[] args) { myChild c1 = new myChild(); c1.mymethod(); Console.ReadLine(); } //Output //Parent class private string & 3 } } 

If you want to get the name of the parent's context you can get that using a parent object.

static void Main(string[] args) { myParent c1 = new myChild(); c1.mymethod(); Console.ReadLine(); } 

Comments

0

If you want to access a field in the derived class, you can define it as protected.

class myParent { public int id = 3; protected string name = "Parent class private string"; public void mymethod() { Console.WriteLine("{0} & {1}", name, id); } } 

and set it in the child constructor

class myChild : myParent { public myChild() { name = "Child class private string"; } } 

Alternatively you can use the virtual/override keyworkds if you define name as a property { get; set; }

class myParent { public int id = 3; protected virtual string name { get; set; } = "Parent class private string"; public void mymethod() { Console.WriteLine("{0} & {1}", name, id); } } class myChild : myParent { protected override string name { get; set; } = "Child class private string"; } 

I never created an instance of the base class.

It is created internally when you instantiate the derived class.

When I invoke c1.mymethod(), why is string name in the myParent class used instead of string name in myChild class since I am invoking a method on myChild object which has a defined string name variable?

Basically your original code is equivalent - in terms of its output - to the above case of a virtual name with a new keyword in the derived class

class myChild : myParent { new string name { get; set; } = "Child class private string"; } 

In that case, the parent's method will display the parent's name, since the child's name is now a different, new variable and it's no longer the one used in the parent's method.

2 Comments

Thanks. Does the statement always hold that a base class instance get created when instantiating a child class? What about creating multiple child class insdtances?
The statement means that all the members of the base class are internally created for the derived class. If you create multiple instances, only static variables are allocated once...