为什么叫我在派生类中调用基类方法的方法? [英] Why does calling a method in my derived class call the base class method?

查看:156
本文介绍了为什么叫我在派生类中调用基类方法的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这个code:

class Program
{
    static void Main(string[] args)
    {
        Person person = new Teacher();
        person.ShowInfo();
        Console.ReadLine();
    }
}

public class Person
{
    public void ShowInfo()
    {
        Console.WriteLine("I am Person");
    }
}
public class Teacher : Person
{
    public new void ShowInfo()
    {
        Console.WriteLine("I am Teacher");
    }
}

当我运行这个code,下面的输出:

When I run this code, the following is outputted:

我的人

然而,你可以看到它是一个实例,如果教师不是,。为什么code做呢?

However, you can see that it is an instance if Teacher, not of Person. Why does the code do that?

推荐答案

有之间的差异虚拟 / 覆盖

There's a difference between new and virtual/override.

您可以想像,一个类,实例化时,无非就是指针表较多,指向实际执行它的方法。下面的图像应该想象这pretty得好:

You can imagine, that a class, when instantiated, is nothing more than a table of pointers, pointing to the actual implementation of its methods. The following image should visualize this pretty well:

现在有不同的方式,一种方法可以被定义。当它与继承使用的每个行为不同。标准的方式总是就像上面的图片说明。如果你想改变这种行为,您可以将不同的关键字到您的方法。

Now there are different ways, a method can be defined. Each behaves different when it is used with inheritance. The standard way always works like the image above illustrates. If you want to change this behavior, you can attach different keywords to your method.

第一个是摘要摘要方法简单地指向无处:

The first one is abstract. abstract methods simply point to nowhere:

如果您的类包含抽象成员,它也需要被标记为摘要,否则编译器不会编译应用程序。您不能创建摘要类的实例,但你可以从他们那里继承并创建继承的类的实例,使用基类定义访问它们。在您的例子,这将是这样的:

If your class contains abstract members, it also needs to be marked as abstract, otherwise the compiler will not compile your application. You cannot create instances of abstract classes, but you can inherit from them and create instances of your inherited classes and access them using the base class definition. In your example this would look like:

public abstract class Person
{
    public abstract void ShowInfo();
}

public class Teacher : Person
{
    public override void ShowInfo()
    {
        Console.WriteLine("I am a teacher!");
    }
}

public class Student : Person
{
    public override void ShowInfo()
    {
        Console.WriteLine("I am a student!");
    }
}

如果调用的行为 ShowInfo 变化的基础上,实现:

If called, the behavior of ShowInfo varies, based on the implementation:

Person person = new Teacher();
person.ShowInfo();    // Shows 'I am a teacher!'

person = new Student();
person.ShowInfo();    // Shows 'I am a student!'

在这两方面,学生教师 S,但他们的行为不同,当他们被要求提醒有关自己的信息。然而,为了让他们的提示信息的方式是一样的:使用类接口

Both, Students and Teachers are Persons, but they behave different when they are asked to prompt information about themselves. However, the way to ask them to prompt their information, is the same: Using the Person class interface.

那么,什么幕后发生了,当您从继承?在实施 ShowInfo ,指针没有指向的无处的不再,它指向的实际执行!当创建一个学生实例,它指向学生取值 ShowInfo

So what happens behind the scenes, when you inherit from Person? When implementing ShowInfo, the pointer is not pointing to nowhere any longer, it now points to the actual implementation! When creating a Student instance, it points to Students ShowInfo:

第二个方法是使用虚拟方法。该行为是相同的,除了你提供的可选的默认在您的基类实现。班,虚拟成员可以被实例化,但继承类可以提供不同的实现。这里是你的code实际上应该看起来像工作:

The second way is to use virtual methods. The behavior is the same, except you are providing an optional default implementation in your base class. Classes with virtual members can be instanciated, however inherited classes can provide different implementations. Here's what your code should actually look like to work:

public class Person
{
    public virtual void ShowInfo()
    {
        Console.WriteLine("I am a person!");
    }
}

public class Teacher : Person
{
    public override void ShowInfo()
    {
        Console.WriteLine("I am a teacher!");
    }
}

的主要区别是,该基地成员 Person.ShowInfo 没有指向的无处的任何更长的时间。这也是原因,为什么你可以创建的实例(因此它不需要被标记为摘要再):

The key difference is, that the base member Person.ShowInfo isn't pointing to nowhere any longer. This is also the reason, why you can create instances of Person (and thus it does not need to be marked as abstract any longer):

您应该注意,这并不为现在从第一图像看起来不同。这是因为虚拟方法指向一个实现的的标准方法的。使用虚拟,你可以告诉,他们的可以(而不是必须)为 ShowInfo 不同的实现。如果你提供不同的实现(使用覆盖),像我一样的教师以上,图像会看的相同摘要。试想一下,我们没有为学生个自定义实现:

You should notice, that this doesn't look different from the first image for now. This is because the virtual method is pointing to an implementation "the standard way". Using virtual, you can tell Persons, that they can (not must) provide a different implementation for ShowInfo. If you provide a different implementation (using override), like I did for the Teacher above, the image would look the same as for abstract. Imagine, we did not provide a custom implementation for Students:

public class Student : Person
{
}

在code会被称为是这样的:

The code would be called like this:

Person person = new Teacher();
person.ShowInfo();    // Shows 'I am a teacher!'

person = new Student();
person.ShowInfo();    // Shows 'I am a person!'

和对学生形象是这样的:

更是解决这个黑客攻击。您可以提供通用类的方法,具有相同的名称作为基类/接口方法。都指向自己的,定制的实现:

new is more a hack around this. You can provide methods in generalized classes, that have the same names as methods in the base class/interface. Both point to their own, custom implementation:

的实施看起来像一个,你提供。该行为不同,根据你的方式访问方式:

The implementation looks like the one, you provided. The behavior differs, based on the way you access the method:

Teacher teacher = new Teacher();
Person person = (Person)teacher;

teacher.ShowInfo();    // Prints 'I am a teacher!'
person.ShowInfo();     // Prints 'I am a person!'

此行​​为可以被通缉,但在你的情况下,它是一种误导。

This behavior can be wanted, but in your case it is misleading.

我希望这是更清楚的事情,了解你!

I hope this makes things clearer to understand for you!

这篇关于为什么叫我在派生类中调用基类方法的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆