我有以下简单的C#代码,但我不理解输出。
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
}
}当我调用c1.mymethod()时,为什么在myParent类中使用string name而不是在myChild类中使用string name,因为我在myChild对象上调用一个方法,该方法有一个定义的string name变量。
我曾经认为,继承意味着简单地将代码从基类复制和粘贴到派生类,以重用代码或保存键笔画。但经过一些研究,情况似乎并非如此。调用继承的方法以某种方式引用基类,这可能解释我代码中的输出。
然而,我仍然不清楚继承的内在运作。例如,我从未创建过基类的实例。基类方法( myParent.mymethod() )应该如何退出?
请帮助澄清我的困惑,并向我指出一些文件。
发布于 2017-02-05 15:23:52
当我调用c1.mymethod()时,为什么在myParent类中使用字符串名称而不是在myChild类中使用字符串名称,因为我在myChild对象上调用一个具有定义的字符串名称变量的方法?
c1.mymethod()方法仅在myParent类中定义。因此,当您调用该方法时,它将使用与该方法最接近的name。换句话说,它将首先在myParent类中搜索该变量,如果找到它,它将使用它。
但是,如果您这样做了(使myMethod虚拟并在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);
}
}然后,它将使用来自name类的myChild变量,因为这是最近的变量。
如果您这样做,您将遇到类似的情况:
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
}
}发布于 2017-02-05 15:32:52
私有是对字段的最严格的访问。这意味着没有其他类可以访问它,只有当前的类。每个类都有自己的一组私有字段。
您的应用程序之所以会这样运行,是因为您的mymethod()成员被声明为公共成员。这意味着任何类都可以调用它。因为您要继承它,所以您可以在myParent中自动获得该方法。它不是复制到myparent中的,而是继承的。而且,由于myChild没有覆盖它,所以对myChild.mymethod()的调用将在myParent上调用它,后者访问它能够访问的唯一私有name字段(在myParent中的字段)。
如果您想继承name字段,那么它将更像您所期望的那样,您需要使字段protected而不是私有字段。
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";
}
}现在,myParent中的变量在实例化时被myChild覆盖。因此,当您调用myChild.mymethod()时,它可以访问新值。
发布于 2017-02-05 15:24:01
来自C#规范:
以下是如何定义继承:
继承意味着类隐式包含其直接基类类型的所有成员,但基类的实例构造函数、析构函数和静态构造函数除外。
现在是关于扩展基类的。
派生类扩展其直接基类。派生类可以向继承的成员添加新成员,但不能删除继承成员的定义。
换句话说,您可以通过添加新定义(或覆盖现有定义)来扩展基类,但不能删除任何定义。
为了让它更干净:
派生类可以通过声明具有相同名称或签名的新成员来隐藏(§3.7.1.2)继承的成员。但是,请注意,隐藏继承成员并不会删除该成员-it,这只会使该成员无法通过派生类直接访问。
您在派生类中所做的工作称为隐藏,正如您从引号中可以看到的那样,它不会删除该成员。
而且,因为在您的MyParent类中,您使用的是在同一个类中定义的name字段,所以它总是会打印它所做的事情。要改变这种行为,您应该先看看虚拟属性。
https://stackoverflow.com/questions/42053596
复制相似问题