C#中的继承误解

时间:2014-01-07 00:41:01

标签: c# inheritance

我试图了解继承在C#中的工作方式。基本上,我有一个基类Base,它具有简单的函数sayIt。该函数使用在子类中重新定义的属性“i”。在这里,它从0重新定义为1.当我运行这个程序时,我得到“0”作为输出而不是“1”这是我所期望的(因为在python中我会得到1)。任何人都可以解释为什么,更重要的是,这是否是C#支持的模式?

class Program
{
    static void Main(string[] args)
    {
        Derived d = new Derived();
        Console.WriteLine(d.sayIt());
        Console.ReadLine();
    }
}

class Base
{
    int _i = 0;
    public int i
    {
        get { return _i; }

    }

    public String sayIt()
    {
        return Convert.ToString(this.i);
    }
}

class Derived : Base
{
    int _i = 1;
    public new int i
    {
        get { return _i; }
    }
}

5 个答案:

答案 0 :(得分:8)

  1. virtual

  2. 中将该属性标记为Base
  3. new替换为override类中属性旁边的Derived

  4. 1。是必要的,因为默认情况下,成员在c#中是非虚拟的。并且 2。是必要的,因为使用new会破坏virtual解析过程,这不是你想要的。

    MSDN上有关于newoverride的好文章:Knowing When to Use Override and New Keywords (C# Programming Guide)

      

    override修饰符扩展了基类方法,new修饰符隐藏了它。

答案 1 :(得分:3)

为了拥有一个可以被派生类型覆盖的函数,你需要使它成为virtual

public virtual int i
{
  get { return _i; }
}

然后在派生类型中,您可以使用override关键字

覆盖行为
public override int i
{
  get { return _i; }
}

答案 2 :(得分:3)

在C#中,您可以选择不允许在类中使用完整的多态/继承行为。

为了获得预期的输出,您的代码应如下所示:(未测试)

class Base
{
    int _i = 0;
    public virtual int i
    {
        get { return _i; }

    }

    public String sayIt()
    {
        return Convert.ToString(this.i);
    }
}

class Derived : Base
{
    int _i = 1;
    public override int i
    {
        get { return _i; }
    }
}

现在你告诉C#解释器我是“虚拟的”,或者子类可以覆盖底层表示。

在旧代码中,您调用的是sayIt(),它位于Base()中。由于我不是虚拟的,因此它不会寻找被覆盖的子项。

基本上在C#中,为了具有适当的继承和多态性,您的代码需要在语法中使用“virtual”然后“override”进行显式声明。

答案 3 :(得分:0)

混淆是因为您在技术上使用名称隐藏在派生类中而不是覆盖基类的行为。使用成员隐藏时,您具有引用的类型将指示实际运行的方法是否存在。 New允许您指示您打算“隐藏”基本实现,以便专门在指定类型上调用您的方法。举例说明:

class Program
    {
        static void Main(string[] args)
        {
            //both 'i' properties exist
            Derived d = new Derived();

            Console.WriteLine(d.i);  // uses the 'i' for this type
            Console.WriteLine(((Base)d).i); // uses the 'i' for this type
            Console.ReadLine();
        }
    }

class Base
{
    int _i = 0;
    public  int i
    {
        get { return _i; }

    }

    public String sayIt()
    {
        //this class and this method doesn't realize the derived class has hid this.i
        return Convert.ToString(this.i);
    }
}

class Derived : Base
{
    int _i = 1;
    public new int i
    {
        get { return _i; }
    }
}

这就是你想要的,我相信能够实现这种模式。

class Base
{
    int _i = 0;
    public  virtual int i
    {
        get { return _i; }

    }

    public String sayIt()
    {
        return Convert.ToString(this.i);
    }
}

class Derived : Base
{
    int _i = 1;
    public override int i
    {
        get { return _i; }
    }
}

希望有所帮助。

-dw

答案 4 :(得分:0)

正如其他人所提到的,在Base中将属性i更改为virtual,并在Derived类的属性中使用override。请参阅下面的示例,了解每种情况的输出以便更好地理解它。您可以看到选项2的输出结果不同。

class Base
{
    int _i = 0;
    public virtual int i
    {
        get { return _i; }
    }

    public String sayIt()
    {
        return Convert.ToString(this.i);
    }
}

class Derived : Base
{
    int _i = 1;
    public override int i
    {
        get { return _i; }
    }
}

您可以通过3种不同的方式实例化代码:

// Option 1
Base a = new Base();
Console.WriteLine(a.i);
// Output using virtual/override --> 0
// Output using new --> 0


// Option 2
Base b = new Derived();
Console.WriteLine(b.i);
// Output using virtual/override --> 1
// Output using new --> 0

// Option 3
Derived c = new Derived();
Console.WriteLine(c.i);
// Output using virtual/override --> 1
// Output using new --> 1

// Option 2
// Derived d = new Base();
// Console.WriteLine(d.i);
// This won't obviously compile